web-dev-qa-db-fra.com

Pourquoi C # n'autorise-t-il pas les propriétés génériques?

Je me demandais pourquoi je ne pouvais pas avoir une propriété générique dans une classe non générique comme je pouvais avoir des méthodes génériques. C'est à dire.:

public interface TestClass
{
   IEnumerable<T> GetAllBy<T>(); //this works

   IEnumerable<T> All<T> { get; } //this does not work
}

J'ai lu le commentaire answer de @ Jon Skeet, mais il ne s'agit que d'une déclaration, qui figure probablement dans les spécifications.

Ma question est pourquoi en fait c'est comme ça? Des problèmes ont-ils été évités avec cette limitation?

25
Sunny Milenov

Techniquement, le CLR ne prend en charge que les types et les méthodes génériques, et non les propriétés. La question est donc de savoir pourquoi il n’a pas été ajouté au CLR. La réponse à cette question est probablement tout simplement «il n’a pas été jugé utile d’apporter suffisamment d’avantages pour en valoir les coûts».

Mais plus fondamentalement, il a été jugé que cela n’apporte aucun avantage, car il n’a pas de sens sémantiquement d’avoir une propriété paramétrée par un type. Une classe Car peut avoir une propriété Weight, mais il n’a aucun sens d’avoir une propriété Weight<Fruit> et une propriété Weight<Giraffe>.

13
Timwi

This Generic Properties Le blog de Julian Bucknall est une très bonne explication. C'est essentiellement un problème d'allocation de tas.

11
JamieSee

Mon hypothèse est qu'il comporte quelques cas pervers qui rendent la grammaire ambiguë. De prime abord, cela semble être un peu délicat:

foo.Bar<Baz>=3;

Cela devrait-il être analysé comme suit:

foo.Bar<Baz> = 3;

Ou:

foo.Bar < Baz >= 3;
2
munificent

Je pense que ne pas utiliser un getter/setter automatique illustre pourquoi cela n’est pas possible sans un "T" défini au niveau de la classe.

Essayez de le coder, la chose naturelle à faire serait la suivante:

IEnumerable<T> _all;
IEnumerable<T> All
{
    get { return _all; }
}

Parce que votre champ utilise "T", alors "T" doit être sur la classe, le CLR sait ce que "T" est.

Lorsque vous utilisez une méthode, vous pouvez différer la définition de "T" jusqu'à ce que vous appeliez réellement la méthode. Mais avec le champ/propriété, "T" doit être déclaré à un endroit, au niveau de la classe.

Une fois que vous avez déclaré T sur la classe, créer une propriété devient assez facile. 

public class TestClass<T>
{
    IEnumerable<T> All { get; }
}

usage:

var myTestClass = new TestClass<string>();
var stuff = myTestClass.All;

Et tout comme le paramètre de type "T" sur une méthode, vous pouvez attendre jusqu'à ce que vous instanciez réellement votre TestClass pour définir ce que sera "T".

0
viggity