2012-06-19 14 views
7

En VB.NET, pude hacer mi código de matemáticas mucho más limpio por System.Math Importación y haciendo referencia a sus métodos directamente:¿Se pueden acortar las referencias matemáticas en C#?

Imports System.Math 
[...] 
Return New Vector3(Sin(az) * Cos(el), Cos(az) * Cos(el), Sin(el)) 

Pero no creo que C# puede utilizar las clases con el fin de acceder a sus métodos implícita, por lo que tengo que hacer algo como:

using System; 
[...] 
return new Vector3(Math.Sin(az) * Math.Cos(el), Math.Cos(az) * Math.Cos(el), Math.Sin(el)); 

Pero eso es feo; ¡necesita su propia barra de desplazamiento !. ¿Hay alguna forma de escribir algo en C# que se parezca a mi código VB.NET? Podría escribir métodos de envoltura local para Sin y Cos, pero ¿eso no reduciría el rendimiento (debido a la sobrecarga de llamadas a funciones)? Y, eso requeriría escribir funciones de contenedor para cada función de Matemáticas que estoy usando en cada clase en que las estoy usando; eso tampoco es tan deseable.

+0

I no creo que el segundo código sea feo, personalmente. – Ryan

+3

Lo hice, cuando comencé a escribir código de esta manera. Pero me acostumbré en unos 5 minutos. –

+0

Actualicé mi respuesta, porque creo que todas nuestras primeras respuestas fueron deficientes. En mi humilde opinión, NINGUNA de esas funciones matemáticas debe estar en la llamada a la función Vector3. Cada uno de esos cálculos debe hacerse, almacenarse y proporcionar mejores nombres de variables para facilitar la lectura del código. – CaffGeek

Respuesta

12

Usted podría dar System.Math un alias con la directiva using:

using M = System.Math; 

return new Vector3(M.Sin(az) * M.Cos(el), M.Cos(az) * M.Cos(el), M.Sin(el)); 

Eso es lo mejor que tengo.

Podría escribir métodos de contenedor local para Sin y Cos, pero ¿no reduciría el rendimiento (debido a la sobrecarga de llamadas a funciones)?

Usted puede, y en ese momento se podría utilizar medicamentos genéricos y otros detalles para que sea aún más conveniente, pero a pesar de ello se hace referencia a una biblioteca de este tipo, a menos que todos los cálculos estaba sucediendo en la misma clase, donde este el código está ocurriendo como métodos.

La cuestión del "rendimiento de la sobrecarga" se responde con "marcos de pila adicionales para algo tan simple que no son perceptibles para las aplicaciones estándar". Si estuvieras en un círculo cerrado, entonces sí, eso sería un problema.

+2

Me lo ganaste – CaffGeek

+2

Si bien esto responde la pregunta del usuario, desaconsejaría usarlo. Esto es mucho MENOS legible que escribir el nombre de la clase en su totalidad. –

+0

Estoy de acuerdo con Chris, esto es mucho menos legible, y hubiera sido bueno por mi parte señalarlo antes de que apareciera y lo mencionara. Esta es la manera de hacer lo que se solicitó, pero "aquellos de nosotros que hemos estado haciendo esto por un tiempo" realmente preferimos ver 'Math.Sin (... 'en nuestra base de código y' usando X = Library.Namespace. Cosa; 'puede ser molesto cuando trato de rastrear algo. +1 Chris. – jcolebrand

9

A partir de C# 6.0 se puede acortar las referencias matemáticas mediante la adición de una declaración using static:

using static System.Math; 

Esto le permite utilizar miembros estáticos del tipo Math sin calificarlo con el nombre del tipo:

public void Foo() 
{ 
    var bar = Sin(8); 
} 

No hay forma de hacer esto "globalmente" ya que no hay forma de aplicar una declaración de uso globalmente, actualmente.

Para aquellos que no utilizan C# 6

pero no habría que reducir el rendimiento (debido a la sobrecarga de llamadas a funciones)?

No me preocuparía. Escriba su código para que sea legible primero. Podemos escribir el método de diferentes maneras. El primero es agregar espacio en blanco:

return new Vector3(
    Math.Sin(az) * Math.Cos(el), 
    Math.Cos(az) * Math.Cos(el), 
    Math.Sin(el) 
); 

También puede ponerlo en un método de ayuda, también.

jcolebrand's answer es bueno también, pero requiere agregar using m = System.Math; en todas partes.

+0

Gracias, esta es una gran respuesta también, aunque probablemente acepte la respuesta de jcolebrand. No sabía que el JIT se alinearía en funciones triviales como las que mencioné; Tendré que investigar eso. Este código será sensible al rendimiento, por lo que la diferencia de la sobrecarga de llamada de función es material. El espacio en blanco también es un buen comentario, aunque ya lo tengo en mi código real (que es considerablemente más complejo que este ejemplo). – Ben

+0

'usando System.Math estático' no parece funcionar para constantes como' PI', aunque los métodos funcionan como se esperaba.Todavía tengo que escribir 'Math.PI' o el código no se compila. Alguien sabe por qué es esto? Algo especial sobre las constantes? – skwear

7

Puede añadir

using M = System.Math; 

y luego simplemente hacer

return new Vector3(M.Sin(az) * M.Cos(el), M.Cos(az) * M.Cos(el), M.Sin(el)); 

pero .... No veo el valor real

De hecho, creo que cada uno de los las variables deben almacenarse, con mejores nombres para representar lo que son. Al mirar esto, no veo lo que se está haciendo.

var sinAz = Math.Sin(az); //Could these be named better? Perhaps with words in the correct domain 
var cosAz = Math.Cos(az); 
var sinEl = Math.Sin(el); 
var cosEl = Math.Cos(el); 

return new Vector3(sinAz * cosEl, cosAz * cosEl, sinEl); 

O mejor, ¿cuáles son los tres parámetros que usa realmente Vector3?

var parm1 = Math.Sin(Az) * Math.Cos(El); //What should parm1, parm2, parm3 be called? 
var parm2 = Math.Cos(Az) * Math.Cos(El); 
var parm3 = Math.Sin(Az); 

return new Vector3(parm1, parm2, parm3); 

Eso mejoraría MUCHO la legibilidad ya que la siguiente persona tendría una mejor comprensión de lo que era la fórmula.

+6

No creo que el voto fuera necesario ... – CaffGeek

+0

No puedo votar dos veces, pero diré que "parm1" es un nombre terrible ... también, estoy de acuerdo con su punto de que no se ve tan bonito, Pero eso es vida. – jcolebrand

+3

Me doy cuenta de que parm1 es un nombre terrible, pero no conozco el dominio lo suficiente como para darle una adecuada ... de ahí el comentario. – CaffGeek

0

No se puede definir un alias para el método en C#, solo para una clase.

+0

Bueno, podría hacerlo con un delegado, creo, pero eso es MUCHO más código repetitivo que no ofrece muchos beneficios, y aún está limitado a ser utilizado solo en esa clase. – jcolebrand

+0

@jcolebrand Sí, pero no creo, ese autor definirá 100500 delegados en cada método matemático que usa – Ribtoks

+0

Exactamente mi punto ;-) – jcolebrand

7

Pero eso es feo; ¡necesita su propia barra de desplazamiento!

Sí, en Stack Overflow, que tiene un ancho corto. Tienes que ponerlo en varias líneas en su lugar:

return new Vector3(Math.Sin(az) * Math.Cos(el), 
        Math.Cos(az) * Math.Cos(el), 
        Math.Sin(el)); 

Personalmente creo que es más fácil de leer todos modos , porque ahora los tres valores diferentes están más claramente diferenciados. Una línea en blanco es un separador más claro que solo una coma, IMO. Cuando tenga varios argumentos lo suficientemente similares como para que puedan perderse juntos, use varias líneas para mayor claridad.

sí, sería en cierto modo bueno si usted podría escribir Sin(az) etc - pero no hay nada en C# que le permitirá hacer eso, así que habría adhieren a formatear el código para facilitar la lectura en su lugar.

+0

De acuerdo, varias líneas como esta son buenas. – Ben

+0

Tengo curiosidad por la idea de usar solo valores intermedios que reflejen la intención, incluso si es un desperdicio (para un programador) de espacio debido a las declaraciones de variables. Estoy dispuesto a apostar a una tarea única como la que podría ser compilada por un compilador inteligente ... – jcolebrand

+0

@jcolebrand: Es más probable que sea optimizado por el JIT que el compilador de C#, pero sí, estoy totalmente feliz usando variables adicionales para la legibilidad. –

5

Usted puede crear una clase que envuelve las llamadas como los métodos de extensión:

public static class MathExtensions { 
    public static double Sin(this double value) { 
     return Math.Sin(value); 
    } 
    public static double Cos(this double value) { 
     return Math.Cos(value); 
    } 
} 

return new Vector3(az.Sin() * el.Cos(), az.Cos() * el.Cos(), el.Sin()); 

El compilador debe inline esas llamadas para que el rendimiento no debe diferir en realidad.

+0

Todavía está agregando algo _delante de '' Sin() ' – jcolebrand

+0

No realmente, estoy moviendo el argumento al frente. Sólo 1 carácter (el '.') se agrega realmente a la longitud, que es la mejor hasta el momento aquí ...;) – Lucero

+0

+1. @jcolebrand, es por eso que he dicho antinatural en mi respuesta semi idéntica :). –

1

También puede utilizar los métodos de extensión, pero resultado se verá más natural (con potencial llamada de función adicional, también es probable que ser inline de distancia):

static double Sin(this double value) { return Math.Sin(value);} 

y uso:

return new Vector3(az.Sin() * el.Cos(),.... 
+0

Si creaste el método de extensión en la clase en la que estabas, podías escaparte sin tener que llamar al contenedor, y yo hubiera dicho _el método de extensión en el mío, pero olvidé su nombre (sabía cómo estaba escrito, olvidé el nombre, en el momento de responder) – jcolebrand

Cuestiones relacionadas