2011-12-18 11 views
18

C'è un modo per dichiarare una funzione generica che il tipo generico sia di tipo o type2?Metodo generico in cui T è type1 o type2

esempio:

public void Foo<T>(T number) 
{ 
} 

Posso vincolo T essere int o lunghi

+1

[Vincoli su Type Parameters (C# Programming Guide)] (http://msdn.microsoft.com/en-us/library/d5x73970.aspx) –

+0

@BoltClock, perché il mio codice si interrompe quando il parametro non è uno dei primitivi (int, lungo, doppio ...) e voglio ottenere errori sulla compilazione non su RunTime – gdoron

+0

Correlati: [Metodo multiplo (OR) di tipo generico] (http://stackoverflow.com/q/10833918) –

risposta

12

È possibile utilizzare generic constraints per limitare il tipo di ciascun argomento generico. Sfortunatamente non esiste un vincolo generico che ti consentirebbe di applicare in fase di compilazione se T è type1 or type2. Non c'è modo di far rispettare in fase di compilazione che il tuo argomento generico possa essere di qualsiasi tipo primitivo (int, long, double, ...).

7

No.

Questo non ha senso; T non avrebbe alcun tipo utilizzabile in fase di compilazione nel metodo.

Invece, è necessario eseguire due metodi di overload.

+3

Penso che abbia senso. Ho un codice che se passi un parametro diverso da quello doppio, decimale, float, int, long etc 'frenerà. Voglio verificarlo alla compilazione. Non ha senso? – gdoron

+0

@gdoron: Dal tuo punto di vista, ha senso. Dal punto di vista del compilatore, non ha senso, dal momento che 'T' non sarebbe un tipo utilizzabile. – SLaks

+0

In questo caso il compilatore può considerare 'T' come il comune di type1 e type2, dove non c'è relazione' T' è 'object' ... – gdoron

0

Non penso che sia attualmente possibile.

This question sulla creazione di una biblioteca matematica come una sorta di coperture sullo stesso terreno e include alcune soluzioni.

4

Utilizzare sovraccaricati metodi invece:

public void Foo(int number) 
{ 
} 

public void Foo(long number) 
{ 
} 

Non è possibile eseguire operazioni aritmetiche sui tipi generici in ogni caso. Si noti che è possibile passare un valore int a un parametro long. Sarà convertito automaticamente in long. Avere un solo metodo con un parametro long potrebbe quindi essere sufficiente.

I linguaggi di programmazione precedenti funzionavano in base al principio "Ce ne può essere uno solo". C# consente di avere diversi metodi con lo stesso nome nella stessa classe, interfaccia o struttura. Questi metodi devono avere una firma diversa. Ciò significa che devono avere un numero diverso di parametri o parametri con tipi diversi (o entrambi). Questo è chiamato overloading del metodo.

+0

Non riesco a scrivere il metodo 20 per ogni tipo di valore numerico. questo è ciò che Generics ** dovrebbe avere ** risolto – gdoron

+0

Le operazioni di aritmetica non sono supportate su parametri di tipo generico. Vedi 'System.Text.StringBuilder' per un esempio. Definisce più di 20 overload '' Append() 'per diversi tipi. –

0

So che questa è una domanda vecchia, e questo non risponde perfettamente, ma puoi farlo con un singolo metodo, piuttosto che creare multipli, o usando vincoli generici ... specialmente utile se hai 20 dispari tipi da controllare.

Ovviamente non si ottiene il tipo compilatore controllare come si fa quando si utilizza un vincolo, ma questo può aiutare in alcune circostanze ...

public void MyMethod<T>() 
{ 
    if (!typeof(T).Equals(typeof(int)) && 
     !typeof(T).Equals(typeof(long))) 
      throw new Exception("T must be int or long"); 

    //your logic here 
} 
0

Ho anche avuto questo problema e penso che ho trovato un soluzione migliore (supponendo che una versione sovraccaricata del metodo non sia sufficiente):

Miscelare Type1 e Type2 senza alcun parallelismo non ha alcun senso come è già stato scritto. Quindi ci deve essere qualsiasi metodo o proprietà accessibile per entrambi i tipi di oggetto.Per assicurarsi che per il compilatore che sono disponibili per l'oggetto, gruppo Type1 e Type2 questi metodi o proprietà con la creazione di un'interfaccia MyInterface e attuazione da Type1 e Type2:

interface MyInterface { 
    void MyCommonMethod(); 
    bool MyCommonProperty { get; } 
} 

class Type1 : MyInterface { 
    void MyCommonMethod() { 
    // TODO: Implement it for Type1 
    } 

    bool MyCommonProperty { 
    get { 
    // TODO: Implement it for Type1 
    } 
    } 
} 

class Type2 : MyInterface { 
    void MyCommonMethod() { 
    // TODO: Implement it for Type2 
    } 

    bool MyCommonProperty { 
    get { 
    // TODO: Implement it for Type2 
    } 
    } 
} 

Ora, di riscrivere il metodo Foo per accettare sia Type1 e Type2, vincolo T di essere un oggetto MyInterface:

public void Foo<T>(T number) where T : MyInterface 
{ 
    throw new NotImplementedException(); 
} 

ho mope questo potrebbe essere utile. :)

6

Per ReferenceType oggetti si può fare

public void DoIt<T>(T someParameter) where T : IMyType 
{ 

} 

...

public interface IMyType 
{ 
} 

public class Type1 : IMyType 
{ 
} 

public class Type2 : IMyType 
{ 
} 

Per il vostro caso utilizzando fino a quando il parametro sarà limitare l'utilizzo di lunghi e int comunque.

public void DoIt(long someParameter) 
{ 

} 

per vincolare a qualsiasi tipo di valore (come: int, double, insomma, decimale) è possibile utilizzare:

public void DoIt<T>(T someParameter) where T : struct 
{ 

} 

Per ulteriori informazioni, è possibile consultare la documentazione ufficiale here

Problemi correlati