161 votes

Pourquoi le constructeur C # ne peut-il pas en déduire le type?

Pourquoi l'inférence de type n'est-elle pas prise en charge pour les constructeurs comme pour les méthodes génériques?

 public class MyType<T>
{
   private readonly T field;
   public MyType(T value) { field = value; }
}

var obj = new MyType(42); // why can't type inference work out that I want a MyType<int>?
 

Bien que vous puissiez contourner ce problème avec une classe d’usine,

 public class MyTypeFactory
{
   public static MyType<T> Create<T>(T value)
   {
      return new MyType<T>(value);
   }
}
var myObj = MyTypeFactory.Create(42);
 

Y a-t-il une raison pratique ou philosophique pour laquelle le constructeur ne supporte pas l'inférence de type?

128voto

Eric Lippert Points 300275

Est-il une raison philosophique pourquoi le constructeur ne peut pas soutenir l'inférence de type?

Pas de. Lorsque vous avez

new Foo(bar)

ensuite, nous avons pu identifier tous les types appelé Foo dans le champ d'application indépendamment de générique arité, et puis faire de la résolution de surcharge sur chaque utilisant une version modifiée de la méthode d'algorithme d'inférence de types. Nous serions alors à créer une "betterness' algorithme qui détermine lequel des deux applicable constructeurs en deux types qui ont le même nom, mais différents génériques arité est le meilleur constructeur. Afin d'assurer la rétrocompatibilité un ctor sur un non-type générique doit toujours gagner.

Est-t-il une raison pourquoi le constructeur ne peut pas soutenir l'inférence de type?

Oui. Même si l'avantage de la fonction l'emporte sur ses coûts, qui sont considérables, ce n'est pas suffisant d'avoir une fonctionnalité de mise en œuvre. Non seulement le dispositif doivent être un gain net, il doit être un grand gain net par rapport à toutes les autres fonctionnalités que l'on pourrait investir dans des. Il dispose également de mieux que de passer que de temps et d'efforts sur la correction de bug, la performance de travail, ainsi que d'autres zones que l'on pourrait mettre cet effort. Et idéalement, il correspondait bien à ce que le "thème" de la libération.

En outre, comme vous l'avez remarque, vous pouvez obtenir les avantages de cette fonction, sans avoir réellement la fonction elle-même, à l'aide d'un modèle de fabrique. L'existence de facile à des solutions de contournement, il est moins probable qu'une entité ne sera jamais mis en œuvre.

Cette fonctionnalité a été sur la liste des fonctions possibles pour un long moment maintenant. Il n'a jamais été n'importe où près de suffisamment élevés sur la liste pour obtenir effectivement mis en œuvre.

18voto

PostMan Points 3825
public class MyType<T> 
{ 
   private readonly T field; 
   public MyType(T value) { field = value; } 
} 

ils peuvent, il n'est pas nécessaire de dire que le constructeur 'que T est" de nouveau, comme vous l'avez déjà fait dans la classe decleration.

aussi votre usine est incorrect, vous devez disposer d' public class MyTypeFactory<T> non seulement public class MyTypeFactory - sauf si vous déclarez l'usine à l'intérieur de l' MyType classe

Modifier les mises à jour:

Eh bien, est de 42 un long, un court, un int, ou quelque chose d'autre?

Disons que vous avez les éléments suivants

class Base
{
   public virtual void DoStuff() { Console.WriteLine("Base"); }
}

class Foo : Base
{
   public override void DoStuff() { Console.WriteLine("Foo");  }
}

Puis vous avez ce

var c = new Foo();

var myType = new MyType(c);

Vous attendez-vous foo ou base? Nous devons dire au compilateur d'utiliser à la place de T

Lorsque vous avez vraiment envie de sur type base

D'où l'

var myType = new MyType<Base>(c);

13voto

Kirk Woll Points 34601

La principale raison pour laquelle l'inférence de type générique ne peut pas fonctionner sur des constructeurs comme vous le souhaitez est que la classe "MyType" n'existe même pas lorsque tout ce que vous avez déclaré est "MyType <T>". Rappelez-vous qu'il est légal d'avoir les deux:

 public class MyType<T> {
}
 

et

 public class MyType {
}
 

Les deux seraient légaux. Comment désambiguïser votre syntaxe si vous déclariez les deux, et que les deux déclaraient un constructeur en conflit.

1voto

Albin Sunnanbo Points 30722

Le constructeur doit avoir la même spécification générique que la classe elle-même. Sinon, il serait impossible de savoir si int dans votre exemple concernerait la classe ou le constructeur.

 var obj = new MyType<int>(42);
 

Serait-ce classe MyType<T> avec constructeur MyType(int) ou classe MyType avec constructeur MyType<T>(T) ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X