2012-06-19 16 views
7

In VB.NET, ho potuto fare il mio codice di matematica molto più pulito per l'importazione System.Math e fa riferimento a suoi metodi direttamente:I riferimenti matematici possono essere abbreviati in C#?

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

Ma non credo che C# possibile utilizzare le classi, al fine di accedere ai propri metodi implicitamente, quindi devo fare qualcosa del tipo:

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

Ma questo è brutto; ha bisogno della propria barra di scorrimento !. C'è un modo per scrivere qualcosa in C# che assomigli al mio codice VB.NET? Potrei scrivere metodi di wrapper locali per Sin e Cos, ma non ridurre le prestazioni (a causa del sovraccarico delle chiamate di funzione)? E ciò richiederebbe la scrittura di funzioni wrapper per ogni funzione matematica che sto usando in ogni classe in cui le sto usando; anche questo non è tanto auspicabile.

+0

I non pensate che il secondo codice sia brutto, personalmente. – Ryan

+3

L'ho fatto, quando ho iniziato a scrivere codice in questo modo. Ma mi ci sono abituato in circa 5 minuti. –

+0

Ho aggiornato la mia risposta, perché penso che tutte le nostre prime risposte fossero al di sotto degli standard. IMHO, NESSUNO di quelle funzioni matematiche dovrebbe essere nella chiamata alla funzione Vector3. Ognuno di questi calcoli dovrebbe essere fatto, memorizzato e dato nomi di variabili migliori per facilitare la lettura del codice. – CaffGeek

risposta

12

Si potrebbe dare System.Math un alias con la direttiva using:

using M = System.Math; 

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

Questo è il migliore che ho ricevuto.

Potrei scrivere metodi di wrapper locali per Sin e Cos, ma non ridurre le prestazioni (a causa del sovraccarico delle chiamate di funzione)?

Si potrebbe, ea quel punto è possibile utilizzare farmaci generici e altre sottigliezze per rendere ancora più conveniente, ma si sarebbe ancora in riferimento a una libreria come questo, a meno che tutti i calcoli stava accadendo nella stessa classe in cui questo il codice si sta verificando come metodi.

Alla domanda "prestazioni da sovraccarico" viene fornita una risposta con "frame di stack aggiuntivi per qualcosa di così semplice non sono visibili per le applicazioni standard". Se fossi in un circuito chiuso, allora sì, sarebbe un problema.

+2

Mi hai battuto su di esso – CaffGeek

+2

Mentre questo risponde alla domanda dell'utente, sconsiglio vivamente di usare questo. Questo è molto meno leggibile che scrivere il nome della classe per intero. –

+0

Sono d'accordo con Chris, questo è molto meno leggibile, e sarebbe stato bello da parte mia segnalarlo prima che si presentasse e lo menzionasse. Questo è il modo di fare ciò che è stato chiesto, ma "quelli di noi che lo hanno fatto per un po '" preferiscono davvero vedere 'Math.Sin (...' nel nostro codebase e 'usando X = Library.Namespace. Cosa? Può essere fastidioso quando cerco di rintracciare qualcosa. +1 Chris. – jcolebrand

9

Come di C# 6.0 è possibile abbreviare i riferimenti di matematica con l'aggiunta di una dichiarazione using static:

using static System.Math; 

Questo consente di utilizzare i membri statici del tipo Math senza qualifiche con il nome del tipo:

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

Non esiste un modo per farlo "globalmente" poiché non esiste un modo per applicare una dichiarazione utilizzando globalmente, al momento.

Per coloro che non utilizzano C# 6

, ma non vorrei che ridurre le prestazioni (a causa del sovraccarico di chiamate di funzione)?

Non me ne preoccuperei. Scrivi il tuo codice leggibile prima. Possiamo scrivere il metodo in modi diversi. Il primo è semplicemente aggiungere uno spazio bianco:

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

È anche possibile inserirlo in un metodo di supporto.

jcolebrand's answer è bello anche farlo, ma è necessario aggiungere uno using m = System.Math; ovunque.

+0

Grazie, anche questa è un'ottima risposta anche se probabilmente accetterò la risposta di jcolebrand. Non sapevo che il JIT avrebbe inline funzioni banali come stavo menzionando; Dovrò esaminarlo. Questo codice sarà sensibile alle prestazioni, quindi la differenza di funzione chiamata overhead è materiale. Anche lo spazio bianco è un buon commento, sebbene l'abbia già nel mio codice reale (che è considerevolmente più complesso di questo esempio). – Ben

+0

'' using statico System.Math' non sembra funzionare per costanti come 'PI', sebbene i metodi funzionino come previsto.Devo ancora scrivere 'Math.PI' o il codice non viene compilato. Qualcuno sa perché questo è? Qualcosa di speciale sulle costanti? – skwear

7

È possibile aggiungere

using M = System.Math; 

e poi basta fare

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

ma .... non vedo il valore reale

In realtà, credo che ciascuno di questi le variabili dovrebbero essere memorizzate, con nomi migliori per rappresentare ciò che sono. Guardando questo, non vedo cosa si sta facendo.

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 meglio, quali sono i tre parametri utilizzati da Vector3 in realtà chiamati?

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); 

Ciò potrebbe migliorare la leggibilità in quanto la persona successiva avrebbe una migliore comprensione di quale fosse la formula.

+6

Non penso che il downvote fosse necessario ... – CaffGeek

+0

Non posso andare su due volte, ma dirò che "parm1" è un nome terribile ... inoltre, sono d'accordo con il tuo punto di vista che non sembra carino, ma questa è la vita. – jcolebrand

+3

Mi rendo conto che parm1 è un nome terribile, ma non conosco abbastanza bene il dominio per dargliene uno corretto ... da qui il commento. – CaffGeek

0

Non è possibile definire un alias per metodo in C#, solo per una classe.

+0

Beh, potresti farlo con un delegato, credo, ma questo è solo un codice molto più standard per non avere molti vantaggi, ed è ancora limitato ad essere usato solo in quella classe. – jcolebrand

+0

@jcolebrand si, ma non credo, quell'autore definirà 100500 delegati per ogni metodo Math che usa – Ribtoks

+0

Esattamente il mio punto ;-) – jcolebrand

7

Ma questo è brutto; ha bisogno della sua barra di scorrimento!

Sì, su Stack Overflow, che ha una larghezza ridotta. Devi mettere su più righe invece:

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

Personalmente penso che sia più leggibile comunque, perché ora i tre diversi valori sono più chiaramente differenziati. Una riga vuota è un separatore più chiaro di una sola virgola, IMO. Quando hai diversi argomenti che sono abbastanza simili da poterli perdere insieme, usa più linee per chiarezza.

Sì, sarebbe in qualche modo bello se si può solo scrivere Sin(az), ecc - ma non c'è niente in C# che vi permetterà di farlo, così mi piacerebbe restare a riformattare il codice per migliorare la leggibilità, invece.

+0

D'accordo, più righe come questa sono buone. – Ben

+0

Sono curioso di pensare solo usando valori intermedi che in realtà riflettono l'intento anche se è uno spreco (per un programmatore) di spazio a causa di dichiarazioni variabili. Sono disposto a scommettere che un incarico una tantum come quello potrebbe essere compilato da un compilatore intelligente ... – jcolebrand

+0

@jcolebrand: È più probabile che sia ottimizzato dal JIT rispetto al compilatore C#, ma sì - Sono totalmente felice usando variabili extra per la leggibilità. –

5

È possibile creare una classe che avvolge le chiamate come metodi di estensione:

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()); 

Il compilatore dovrebbe inline quelle chiamate in modo che le prestazioni non dovrebbe differire molto.

+0

Stai ancora aggiungendo qualcosa _in front of_ 'Sin()' – jcolebrand

+0

Non proprio, sto spostando l'argomento in primo piano. Solo 1 carattere (il '.') è aggiunto davvero alla lunghezza, che è il migliore finora qui ...;) – Lucero

+0

+1. @jcolebrand, Ecco perché ho detto innaturale nella mia risposta semi-identica :). –

1

È inoltre possibile utilizzare metodi di estensione, ma risultato sarà un aspetto più innaturale (con potenziale chiamata di funzione in più, anche si rischia di essere inline di distanza):

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

E l'uso:

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

Se hai reso il metodo di estensione nella classe in cui ti trovavi potresti andare via senza dover chiamare il contenitore, e avrei _said_ metodo di estensione nel mio, ma ho dimenticato il nome di esso (sapevo come era scritto, dimenticato il nome, nel momento della risposta) – jcolebrand

Problemi correlati