C # - Appeler un constructeur de structure qui a tous les paramètres par défaut
Je suis tombé sur cette question aujourd'hui, lors de la création d'un struct
de tenir un tas de données. Voici un exemple:
public struct ExampleStruct
{
public int Value { get; private set; }
public ExampleStruct(int value = 1)
: this()
{
Value = value;
}
}
A l'air bien et dandy. Le problème est que lorsque j'essaie d'utiliser ce constructeur sans spécifier de valeur et désireux d'utiliser la valeur par défaut valeur de 1 pour le paramètre:
private static void Main(string[] args)
{
ExampleStruct example1 = new ExampleStruct();
Console.WriteLine(example1.Value);
}
Ce code sorties 0
et n'a pas de sortie 1
. La raison en est que toutes les structures ont des paramètres des constructeurs. Donc, comme comment je vais appeler this()
mon explicite du constructeur, dans Main
la même chose se produit lorsque new ExampleStruct()
est fait appel ExampleStruct()
mais pas d'appel ExampleStruct(int value = 1)
. Depuis, il le fait, il utilise int
's valeur par défaut de 0 comme Value
.
Pour aggraver les choses, mon code est de vérifier que int value = 1
paramètre est à l'intérieur d'une plage valide dans le constructeur. Ajoutez à cela le ExampleStruct(int value = 1)
constructeur ci-dessus:
if(value < 1 || value > 3)
{
throw new ArgumentException("Value is out of range");
}
Donc, pour le moment, le constructeur par défaut en fait créé un objet qui n'est pas valide dans le contexte que j'en ai besoin pour. Quelqu'un sait comment je peux soit:
- A. Appeler le
ExampleStruct(int value = 1)
constructeur. - B. comment Modifier les valeurs par défaut sont remplis pour l'
ExampleStruct()
constructeur. - C. Quelques autres suggestions option.
Aussi, je suis conscient que je pourrais utiliser un domaine comme celui-ci à la place de mon Value
propriété:
public readonly int Value;
Mais ma philosophie est d'utiliser des champs en privé, sauf s'ils sont const
ou static
.
Enfin, la raison pour laquelle je suis à l'aide d'un struct
au lieu d'un class
est parce que c'est tout simplement un objet de détenir des données mutable, doit être entièrement rempli lorsqu'il est construit, et lorsqu'il est passé en tant que paramètre, ne devrait pas pouvoir être null
(depuis qu'il est passé par valeur comme un struct
), qui est ce struct sont conçus pour.
source d'informationauteur Michael Yanni
Vous devez vous connecter pour publier un commentaire.
En fait, MSDN a quelques bons conseils sur la
struct
Avis qu'ils sont des considérations pour considérant un
struct
et il n'est jamais un "ce devrait toujours une struct". C'est parce que le choix d'utiliser unstruct
peut avoir la performance et l'utilisation des répercussions (positives et négatives) et doit être choisi avec soin.Avis, en particulier, qu'ils ne recommandent pas de
struct
pour des choses > 16 octets (alors que le coût de la copie devient plus cher que la copie d'une référence).Maintenant, pour votre cas, il n'y a vraiment pas de bonne façon de le faire d'autre que de créer une usine à générer un
struct
pour vous dans un état par défaut ou de faire une sorte detrick
dans votre propriété pour faire l'initialisation lors de la première utilisation.Rappelez-vous, un
struct
est censé travailler, tels quenew X()
==default(X)
c'est un nouvellement construitstruct
contiendra les valeurs par défaut pour tous les champs de lastruct
. C'est assez évident, puisque C# sera pas vous permettent de définir un constructeur sans paramètre pour unstruct
mais il est curieux qu'ils permettent à tous les arguments par défaut sans avertissement.Donc, j'avais en fait vous suggérons de bâton avec un
class
et de le rendre immuable et il suffit de cocher pournull
sur les méthodes qu'il reçoit.Cependantsi vous avez absolument doit ont un
struct
pour d'autres raisons, mais s'il vous plaît prendre en compte les coûts destruct
telles que copier-plâtres, etc - vous pouvez le faire:Notez que par défaut, le
Nullable<int>
seranull
(qui est,HasValue == false
), donc si cela est vrai, nous n'avons pas encore, et peut utiliser le null-coalescence de l'opérateur pour retourner à nos défaut de1
à la place. Si nous ne défini dans le constructeur, il sera non nulle, et prenez plutôt cette valeur...Je ne pense pas que c'est une bonne conception pour avoir un
struct
ExampleStruct
tels quec'est à dire la valeur de tous les champs d'instance sont à zéro/faux/null, est pas une valeur valide de la struct. Et comme vous le savez, quand vous dites
c'est exactement le même que
default(ExampleStruct)
et vous donne la valeur de votre structure où tous les domaines (y compris les "produits" les champs de l'auto-propriétés) sont égaux à zéro.Peut-être que vous pourriez faire ceci:
Je suppose que le compilateur est réellement de la sélection automatique par défaut ctor pour les structures ici http://msdn.microsoft.com/en-us/library/aa288208(v=vs. 71).aspxplutôt que d'utiliser votre ctor avec les valeurs par défaut.
ajouté les références:
http://csharpindepth.com/Articles/General/Overloading.aspx (Section paramètres facultatifs)
Bien que certaines langues (CIL si rien d'autre) permettra de définir une structure constructeur tel que
new T()
a mis quelque chose d'autre que leur "tous les zéros" est par défaut, C# et vb.net (et probablement la plupart des autres langues) prenez avis que, puisque les choses comme les éléments d'un tableau et de champs de classe doivent toujours être initialisé àdefault(T)
et depuis avoir leur être initialisée à quelque chose qui ne correspond pas ànew T()
serait source de confusion, les structures ne devraient pas définirnew T()
pour signifier quelque chose d'autre quedefault(T)
.Je suggère que, plutôt que d'essayer de jinx un paramètre par défaut dans un constructeur paramétré, il vous suffit de définir un statique de la structure de propriété qui renvoie par défaut de votre choix de la valeur, et de remplacer chaque occurrence de
new ExampleStruct()
avecExampleStruct.NiceDefault;
.2015 Additif
Il semble que C# et VB.NET cela peut faciliter l'interdiction de la définition de sans paramètre struct constructeurs. Cela peut entraîner une instruction comme
Dim s = New StructType()
à attribuers
une valeur qui est différente de la valeur donnée à de nouveaux éléments de tableau de typeStructType
. Je ne suis pas terriblement envie sur le changement, étant donné quenew StructType
est souvent utilisé dans des endroits où quelque chose d'analogue à C#'sdefault(StructType)
serait plus approprié si elle existait. VB.NET permettraitDim s As StructType = Nothing
mais qui semble plutôt à l'eau de rose.pourquoi avez-vous
public ExampleStruct(int value = 1) : this()
?ne devrait-elle pas être
public ExampleStruct(int value = 1)
? Je pense que le:this()
est la création de la non-paramètre du constructeur.