298 votes

Pourquoi ne ' t je définir un constructeur par défaut pour un struct dans .NET ?

Dans .NET une valeur de type (C# struct) ne peut pas avoir un constructeur sans paramètres. Selon ce post, c'est mandaté par la CLI spec. Ce happes est que pour chaque type de valeur d'un constructeur par défaut est créé (par le compilateur?) qui initialisé tous les membres à zéro (ou null).

Personne ne sait pourquoi il n'est pas autorisé à définir un constructeur par défaut?

Un trivial utilisation est pour les nombres rationnels

public struct Rational {
    private long numerator;
    private long denominator;

    public Rational(long num, long denom)
    { /* Todo: Find GCD etc. */ }

    public Rational(long num)
    {
        numerator = num;
        denominator = 1;
    }

    public Rational() // This is not allowed
    {
        numerator = 0;
        denominator = 1;
    }
}

L'aide de C# par défaut Rationnelle est - 0/0 qui n'est pas si cool.

P. S. par défaut des paramètres de l'aider à résoudre ce pour C#4.0, ou le CLR défini dans le constructeur par défaut être appelé?


Edit: Jon Skeet répondu:

Pour utiliser votre exemple, que voudriez-vous arriver si quelqu'un a fait:

 Rational[] fractions = new Rational[1000];

Faut-il courir à travers votre constructeur 1000 fois?

Assurez-vous qu'il le devrait, c'est pourquoi j'ai écrit le constructeur par défaut en premier lieu, le CLR doit utiliser la valeur par défaut réinitialisation de constructeur lorsque aucun par défaut explicite ctor est défini, de cette façon, vous ne payez que pour ce que vous utilisez. Ensuite, si je veux un conteneur de 1000 par défaut Rationals (et vous voulez optimiser loin les 1000 constructions), je vais utiliser un List<Rational> plutôt qu'un tableau.

C'est pourquoi, dans mon esprit, n'est pas suffisamment forte pour empêcher la définition d'un constructeur par défaut.

217voto

Jon Skeet Points 692016

EDIT: j'ai édité la réponse ci-dessous en raison de Grauenwolf de l'aperçu de la CLR.

Le CLR permet de types de valeur à avoir sans paramètre constructeurs, mais le C# n'a pas. Je crois que c'est parce qu'elle introduirait attend à ce que le constructeur appelle quand il ne serait pas. Par exemple, considérez ceci:

MyStruct[] foo = new MyStruct[1000];

Le CLR est capable de le faire de façon très efficace, juste par l'allocation de la mémoire et de la réinitialisation. Si elle avait pour exécuter le MyStruct constructeur de 1000 fois, ce serait beaucoup moins efficace. (En fait, il n'a pas - si vous ne avoir un constructeur sans paramètre, il ne va pas s'exécuter lorsque vous créez un tableau, ou si vous avez une non initialisée variable d'instance.)

La règle de base en C# est "la valeur par défaut pour n'importe quel type de ne peut pas compter sur toute l'initialisation". Maintenant, ils pourraient avoir admis sans paramètre constructeurs à définir, mais alors pas nécessaire que le constructeur à être exécutée dans tous les cas - mais qui aurait conduit à une plus grande confusion. (Ou au moins, je crois donc que l'argument).

EDIT: Pour utiliser votre exemple, que voudriez-vous arriver si quelqu'un a fait:

Rational[] fractions = new Rational[1000];

Faut-il courir à travers votre constructeur 1000 fois?

  • Si pas, nous nous retrouvons avec 1000 invalide rationnels
  • Si c'est le cas, nous avons potentiellement perdu de la charge de travail si nous sommes sur le point de remplir le tableau avec les valeurs réelles.

EDIT: (Répondre à un peu plus de la question) Le constructeur sans paramètre n'est pas créé par le compilateur. Types de valeur n'ont pas les constructeurs aussi loin que le CLR est concernée - même si il s'avère qu'il peut si vous l'écrivez en IL. Lorsque vous écrivez "new Guid()" en C# qui émet différents IL à ce que vous obtenez si vous appelez un constructeur normal. Voir ce DONC, la question un peu plus sur cet aspect.

Je soupçonne qu'il n'y a pas tout les types de valeur dans le cadre sans paramètre constructeurs. Pas de doute, NDepend pourrait me dire si j'ai demandé gentiment assez... Le fait que C# interdit c'est un assez gros indice pour moi de penser que c'est probablement une mauvaise idée.

53voto

user42467 Points 822

Une structure est un type de valeur et un type de valeur doit avoir une valeur par défaut dès qu'elle est déclarée.

MyClass m;
MyStruct m2;

Si vous déclarez des deux champs comme ci-dessus sans l'instanciation, puis casser le débogueur, m sera nulle mais m2 ne sera pas. Compte tenu de cela, un sans paramètre contrsuctor aurait aucun sens, et en fait tous tout constructeur sur une struct n'est attribuer des valeurs, la chose elle-même existe déjà juste en la déclarant. En effet m2 pourrait tout à fait heureux d'être utilisé dans l'exemple ci-dessus et ont ses méthodes appelées, le cas échéant, et de ses champs et ses propriétés manipulés!

14voto

Joel Coehoorn Points 190579

Plus courte explication:

En C++, struct et class étaient les deux faces d'une même pièce de monnaie. La seule vraie différence est que l'un est public par défaut et l'autre privé.

Dans .NET, il y a plus de différence entre une structure et une classe. La chose principale est que struct fournit une valeur de type sémantique, tandis que la classe de référence de type sémantique. Lorsque vous commencez à penser aux conséquences de ce changement, d'autres changements de commencer à faire plus de sens en tant que bien, y compris le constructeur de comportement que vous décrivez.

1voto

Jonathan Allen Points 23540

Vous ne pouvez pas définir un constructeur par défaut, parce que vous utilisez c#.

Structs peuvent avoir des constructeurs par défaut dans .NET, même si je ne sais pas du tout langage spécifique qui prend en charge.

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