2011-08-17 7 views
12

È possibile specificare un vincolo su una classe generica che non consente determinati tipi? Non so se sia possibile e se lo è, non sono sicuro di quale sarebbe la sintassi. Qualcosa di simile:Come specificare i tipi non consentiti in un vincolo di .NET Generics?

public class Blah<T> where : !string { 
} 

Non riesco a trovare alcuna notazione che consenta tale restrizione.

+0

non pensare che questo sia possibile, ma perché avresti bisogno di qualcosa del genere? – Carsten

+0

Qual è il comportamento desiderato quando qualcuno cerca di passare un tipo che non è supportato? –

+0

In realtà stavo tentando di escludere il tipo di stringa, ma si scopre che usando T: struct funziona per quello che sto cercando di fare poiché la mia classe non funzionerà comunque per tipi complessi. –

risposta

11

Il più vicino possibile è un vincolo di runtime.

Modifica: Originariamente ho inserito il controllo di runtime nella chiamata del costruttore. Questo in realtà non è ottimale, poiché incorre in ogni istante in ogni istanziazione; Credo che sarebbe molto più sensato mettere il segno di spunta nella costruttore statico , che verrà richiamato una volta per ogni tipo viene utilizzata come parametro T per il vostro tipo Blah<T>:

public class Blah<T> { 
    static Blah() { 
     // This code will only run ONCE per T, rather than every time 
     // you call new Blah<T>() even for valid non-string type Ts 
     if (typeof(T) == typeof(string)) { 
      throw new NotSupportedException("The 'string' type argument is not supported."); 
     } 
    } 
} 

Ovviamente non è l'ideale, ma se si mettere questo vincolo in posizione e documentare il fatto che string non è un argomento di tipo supportato (ad esempio, tramite commenti XML), si dovrebbe ottenere da qualche parte vicino a l'efficacia di un vincolo in fase di compilazione.

+1

in genere inserisco i vincoli non espressi in C# nel costruttore della classe. – CodesInChaos

+0

Per includere il tipo che può essere risolto come stringa: if (typeof (stringa) .IsAssignableFrom (typeof (T))) lancia la nuova NotSupportedException – Rasmus

4

No, non è possibile specificare direttamente i vincoli di tipo "negato".

+0

Esiste un metodo indiretto, altro che qualcosa come Asserire che il typeof (T) non è qualcosa? – SirPentor

+0

@SirPentor Non come parte del vincolo di tipo, sebbene si possa fare qualcosa del genere nel codice. – Donut

2

I vincoli possono essere solo vincoli positivi, come indicato nello documentation.

L'unica cosa che puoi fare è specificare quali tipi può essere messo nel tipo generico, ma non si può specificare quali non può essere messo in loro.

1

Qui ci sono i vincoli domestici (more detail)

  • dove T: struct
  • dove T: classe
  • dove T: new()
  • dove T: [nome della classe di base]
  • dove T: [nome interfaccia]
  • dove T: U (L'argomento di tipo fornito per T deve essere o derivare dall'argomento fornito per U)