2009-07-24 26 views
21

Mi chiedevo se è possibile aggiungere più vincoli generici?C# Vincoli generici multipli

Ho un metodo Add che prende un oggetto (O-mail, telefono o indirizzo), quindi stavo pensando qualcosa del tipo:

public void Add<T>(T Obj) 
    where T : Address 
    where T : Email 
    where T : Phone 
{ 
    if (Obj is Address) 
     m_Address.Add(Obj as Address); 
    else if (Obj is Email) 
     m_Email.Add(Obj as Email); 
    else 
     m_Phone.Add(Obj as Phone); 
} 

Ma io continuo a ricevere:

"A constraint clause has already been specified for type parameter 'T'. All of the constraints for a type parameter must be specified in a single where clause."

risposta

25

Non puoi farlo. Perché non avere solo tre metodi e lasciare che il compilatore faccia il duro lavoro per te?

public void Add(Address address) { m_Address.Add(address); } 
public void Add(Email email) { m_Email.Add(email); } 
public void Add(Phone phone) { m_Phone.Add(phone); } 
+1

Così, come enumerare più di un insieme generico quali ** ** fortemente tipizzata di 'types' eterogenea come qualsiasi altro normale IEnumerable ? –

+0

@AngshumanAgarwal - Presumo che questo non sia un metodo 'Add' su una collezione in quanto non avrebbe molto senso. –

+1

Supponiamo, se ho un'interfaccia 'IWalk, IRun e IBothWalkRun'. Ora, voglio creare una raccolta eterogenea fortemente tipizzata di tutti i tipi e scorrere su in modo tale che stampi tutti IWalk, IRun e IBothWalkRun? Ha senso? –

1

In tal caso, non mi preoccuperei, come si confrontano comunque i tipi. Utilizzare questo:

public void Add(object Obj) 
{ 
    if (Obj is Address) 
     m_Address.Add(Obj as Address); 
    else if (Obj is Email) 
     m_Email.Add(Obj as Email); 
    else if (Obj is Phone) 
     m_Phone.Add(Obj as Phone); 
    else 
     return; 
} 

Non penso che siano supportate più clausole. Potresti anche avere sovraccarichi di metodo separati.

5

Come creare un'interfaccia o una classe base per questi tre tipi?

Ma guardando il tuo codice, sembra che tu non stia usando il generico abbastanza bene. Il punto di utilizzo generico è che non è necessario eseguire il cast in un particolare tipo (in questo caso, lo sei).

9

CLR non consente l'ereditarietà multipla, che è esattamente ciò che si sta tentando di esprimere. Si desidera che T sia Address, Email e Phone allo stesso tempo (presumo che si tratti di nomi di classe). Quindi è impossibile. Qual è l'evento più, questo intero metodo non ha senso. Dovrai introdurre un'interfaccia di base per tutte e tre le classi o utilizzare tre overload di un metodo Add.

+9

@Anton, penso che l'OP chieda dei vincoli OR (non AND). –

2

In questo caso non si ottiene alcun beneficio reale dai generici. Vorrei solo creare diversi metodi Add per ogni parametro Type.

-4

dove T: C1, C2, C3. Virgola separata per i vincoli. Prova a utilizzare la classe base o le interfacce.

+4

Questo non funziona, quindi il meno 1 –

0

Come altri hanno già detto, nel caso specifico è necessario utilizzare l'ereditarietà o l'overloading di metodi anziché i generici. Tuttavia, se è necessario creare un metodo generico con più vincoli, è possibile farlo in questo modo.

public void Foo<T>() where T : Bar, IBaz, new() 
{ 
    // Your code here 
}