2009-04-08 11 views
6

Sto tentando di aggiungere un vincolo a un metodo generico in modo da verificare i tipi di valore ValueTypes, Stringhe o Nullable.Vincolo generico a ValueTypes, Stringhe e Nullable of ValueTypes

Il problema è che:

  • tipi di valore sono montanti
  • stringhe sono tipi di riferimento immutabili
  • annullabile sono tipi di valore, ma non saranno accettate in un "dove S: struct" tipo di vincolo .

Quindi qualcuno sa se c'è un modo in cui posso accettare questi e solo questi tipi in un vincolo generico?

Il problema è che sto tentando di accettare un parametro Expression<Func<T, S> che rappresenterà una proprietà di questi tipi per un determinato oggetto.

La funzionalità sarebbe qualcosa di simile alla seguente (si noti il ​​codice non ha alcun senso ed è solo qualcosa di veloce per avere un'idea di quello che sto cercando):

public class Person 
{ 
    public string Name {get; set;} 
    public DateTime? DOB {get; set;} 
    public int NumberOfChildren {get; set;} 
    public Car CurrentCar {get; set;} 
} 

--- 

internal void MyGenericMethod<T, S>(T myObject, Expression<Func<T, S> property){...} 

Person myPerson = new Person(); 
MyGenericMethod(myPerson, p => p.Name); //S would be a string 
MyGenericMethod(myPerson, p => p.DOB); //S would be a DateTime? 
MyGenericMethod(myPerson, p => p.NumberOfChildren); //S would be a struct 

I tre chiamate sopra dovrebbero essere tutti accettati, ma non il seguente:

MyGenericMethod(myPerson, p => p.CurrentCar); //S would be a class and shouldn't compile 

Grazie in anticipo

AGGIORNAMENTO: Grazie Anton e Marc. MyGenericMethod ha 4 diverse firme che accettano parametri extra, ecco perché non mi piace l'idea di creare 3 differenti (struct, nullable, string) per ciascuno dei 4 esistenti ... sarebbe un incubo da mantenere!

risposta

7

L'unica cosa che posso venire in mente è un insieme di tre funzioni (sans Expression<> roba):

MyGenericFunction<T>(T t) 
    where T : struct 

MyGenericFunction<T>(T? t) 
    where T : struct 

MyGenericFunction(string s) 

UPDATE Dato che ci sono vari sovraccarichi di un metodo, posso suggerire:

class Holder 
{ 
    private object value; 

    public Holder(object value) 
    { 
     this.value = value; 
    } 

    public static implicit operator Holder(DateTime dt) 
    { 
     return new Holder(dt); 
    } 

    public static implicit operator Holder(string s) 
    { 
     return new Holder(s); 
    } 

    // Implicit conversion operators from primitive types 
} 

Così il metodo diventa

MyGenericMethod(Holder h); 

Ancora molto ingombrante, ma tuttavia potrebbe funzionare.

+0

Potrebbe avere senso definire "struct Holder". Quindi diventa "zucchero sintattico" in fase di compilazione, il cui scopo è specificare cosa è e cosa non è legale. Ma il risultato del runtime sarebbe efficiente - elimina l'allocazione/garbage collection necessaria per una classe. – ToolmakerSteve

Problemi correlati