10
votes

Mise en œuvre de types nullables dans l'interface générique

Donc, dans une question précédente, j'ai posé des questions sur la mise en œuvre d'une interface générique avec une classe publique et un bingo, cela fonctionne. Cependant, l'un des types que je cherche à passer est l'un des types nullables intégrés tels que: INT, GUID, String, etc.

Voici mon interface: P>

public class TestInterface : IOurTemplate<MyCustomClass, Int32>
{
    public IEnumerable<MyCustomClass> List()
    {
        throw new NotImplementedException();
    }

    public MyCustomClass Get(Int32 testID)
    {
        throw new NotImplementedException();
    }
}


0 commentaires

3 Réponses :


7
votes

types nullables ne satisfait pas Classe ou struct contraintes:

C # Spécification de langue V3.0 (section §10.1.5: Type des contraintes de paramètre):

La contrainte de type de référence Spécifie qu'un argument de type utilisé pour le paramètre type doit être un type de référence. Tous les types de classe, types d'interfaces, types de délégués, types de réseau et paramètres de type connus pour être un type de référence (tel que défini ci-dessous) satisfaire à cette contrainte. La contrainte de type de valeur Spécifie qu'un argument de type utilisé pour le paramètre type doit être un type de valeur non nullable.

Tous les types de structure non nullables, types d'énumjets et paramètres de type ayant la contrainte de type de valeur répondent à cette contrainte. Notez que, bien que classé comme type de valeur, un type nullable (§4.1.10) ne satisfasse pas la contrainte de type de valeur. Un paramètre de type ayant la contrainte de type de valeur ne peut également avoir la contrainte de constructeur. < / p>


6 commentaires

Alors, quelle est votre recommandation?


Si vous n'avez pas besoin de contraintes, supprimez-les. Si vous souhaitez utiliser des types nullables uniquement, ajoutez une contrainte de type de valeur ( où T: struct ) et utilisez t? dans la définition de la classe.


Quel est le point d'avoir une telle règle? Sûrement nullable devrait satisfaire la contrainte de la structure, car c'est une structure.


@buffjape Eh bien, c'est une structure spéciale et ne satisfait pas la contrainte. NULLLABLE est traité spécialement par l'exécution: quand une valeur non nullable nullable est en boîte, elle est en boîte sous la forme d'un t struct, pas nullable . Lorsqu'un null valeur nullable est en boîte, il renvoie simplement une référence null. La justification est: imaginez int? a = null; si (a == null) {...} objet o = a; Si (O == NULL) {...} , vous voulez probablement tous les deux si Les corps doivent être exécutés de manière constante. En fait, en début de bêtres de .NET 2.0 qui introduisait des types nullables, nullable était juste une structure régulière et ? était juste une syntaxe ...


... sucre pour manipuler nullable valeurs. En raison de cette divergence, Microsoft a décidé de modifier le CLR pour traiter nullable spécialement. Vous ne pouvez pas coder votre propre myscullable struct et obtenir la même sémantique d'exécution.


Ils ont donc mis en œuvre nullable comme un pointeur (pas une structure ou une classe), très efficace, mais ils devaient ensuite générer un code différent. Le compilateur génère déjà un code différent pour les paramètres de type de classe et de structure. Pourquoi Microsoft n'a-t-il pas fini le travail et faire de même pour Nullable (plutôt que de l'exclure des génériques dans ce qui semble être une manière arbitraire)?



7
votes

Je ne ferais pas vraiment cela, mais c'est probablement le seul moyen de le faire fonctionner. XXX


0 commentaires

1
votes

Une raison pour laquelle vous devez limiter le type U à la classe?

public interface IOurTemplate<T, U>
    where T : class
{
    IEnumerable<T> List();
    T Get(U id);
}

public class TestInterface : IOurTemplate<MyCustomClass, Int32?>
{
    public IEnumerable<MyCustomClass> List()
    {
        throw new NotImplementedException();
    }

    public MyCustomClass Get(Int32? testID)
    {
        throw new NotImplementedException();
    }
}


0 commentaires