2009-02-11 6 views
18
parameterless

Est-il possible de cacher le constructeur parameterless d'un utilisateur en C#cacher constructeur sur struct

Je veux les forcer à utiliser toujours le constructeur avec des paramètres

par exemple cette classe de position

public struct Position 
{ 
    private readonly int _xposn; 
    private readonly int _yposn; 

    public int Xposn 
    { 
     get { return _xposn; } 
    } 

    public int Yposn 
    { 
     get { return _yposn; } 
    } 

    public Position(int xposn, int yposn) 
    { 
     _xposn = xposn; 
     _yposn = yposn; 
    }   
} 

Je veux que les utilisateurs soient en mesure de nouveau une position en spécifiant les coordonnées x et y

Cependant, le constructeur parameterless est toujours availiable

Je ne peux pas le rendre privé . Ou même définir comme du public

J'ai lu ce Why can't I define a default constructor for a struct in .NET?

mais il ne marche pas vraiment aider

Si cela est impossible - quelle est la meilleure façon de détecter si la position que je suis être passé a valeurs?

Vérification de l'appartenance à chaque champ de propriété? Y a-t-il un moyen plus lisse?

grâce

Répondre

19

Non, vous ne pouvez pas faire cela. Comme vous l'avez dit, similar question a déjà été posée - et je pensais que la réponse était assez claire que vous ne pouviez pas le faire.

Vous pouvezcreate a private parameterless constructor for a struct, mais pas en C#. Cependant, même si vous le faites que cela ne permet pas vraiment - parce que vous pouvez facilement travailler autour:

MyStruct[] tmp = new MyStruct[1]; 
MyStruct gotcha = tmp[0]; 

Ce sera la valeur par défaut de MyStruct - la « zéros » valeur - sans jamais appeler un constructeur .

Vous pouvez facilement ajouter une méthode Validate à votre structure et l'appeler chaque fois que vous en avez reçu un en tant que paramètre, certes.

+3

Je vois cela comme un problème d'utilisabilité plus que toute autre chose. Le constructeur par défaut peut créer un objet _valid_, mais pour beaucoup de structures, ce ne sera pas ce que l'utilisateur voudra ou attendra. Néanmoins, certaines personnes utiliseront ce constructeur par défaut simplement parce que c'est la première option que leur IDE leur donne.Et puis ils auront des bugs confus causés par des structures éliminées qui auraient dû être remplies de données, ou ils perdront du temps à essayer de comprendre pourquoi ils ne peuvent pas définir les propriétés sur une structure immuable. Du point de vue de la conception de l'API, je souhaite qu'il soit possible de masquer le constructeur par défaut. –

+1

+1 @ MB. Un constructeur par défaut privé serait utile, même si un "imbécile" déterminé peut contourner ce problème. En tant que sel C++, je pense à 'private' comme un indice pour ne pas vous tirer dans le pied, il y a toujours une solution de travail en utilisant des pointeurs. Et la sémantique des tableaux peut être prise en compte en ne permettant pas la création de tableaux de ces structures. –

+0

@roryapL Correction, merci. –

2

Eh bien un struct est littéralement une déclaration de la façon dont la mémoire siégera.

Même lorsque vous utilisez un objet, le pointeur d'objets est déclaré, qu'il soit nul ou non.

La raison pour laquelle vous ne pouvez pas masquer le constructeur est que la structure exige que le CLR puisse le créer en interne, il doit le faire.

Vous pouvez convertir cette structure en objet pour réaliser cette tâche. Ou utilisez-vous une analyse statique pour vous assurer qu'il est initialisé avant de l'utiliser?

struct point 
{ 
    int xpos; 
    int ypos; 
} 

Avoir un google pour les objets immuables, cela semble être ce que votre après. Je crois qu'ils cherchent à ajouter cette fonctionnalité (mais pas en C# 4) à la langue elle-même, parce que c'est une exigence commune. Y a-t-il un besoin spécifique pour une structure ici?

+0

Qu'entendez-vous par là? utilisez l'analyse statique pour vous assurer qu'il est initialisé vous voulez dire que chaque champ a une valeur? – ChrisCa

+0

Vous pouvez exécuter un outil d'analyse statique avec une règle pour vous assurer qu'à chaque fois que quelqu'un utilise le type dans son code, les deux valeurs sont initialisées. ou vous pourriez faire un jeu de jambes fantaisie en le déclarant comme un objet pour faire la vérification, et ensuite passer à une structure dans la version de construction. – Spence

4

Non ne peut pas le cacher. Les structures ne peuvent pas redéfinir le constructeur de zéro arg, donc sa visibilité ne peut pas être redéfinie.

+0

Eh bien, .NET vous permet de fournir un constructeur sans paramètre personnalisé - mais vous ne pouvez pas le faire * directement * en C# et cela n'aide pas beaucoup, car vous pouvez facilement contourner ce problème. –

1

Vous ne pouvez pas créer de structure avec un constructeur privé sans paramètre ou même déclarer un constructeur sans paramètre. Vous devriez le changer en classe. Les structures ne permettent pas de déclarer un constructeur sans paramètre.

De l'Structs Tutorial sur MSDN:

Structs peut déclarer les constructeurs, mais ils doivent prendre des paramètres. C'est une erreur de déclarer un constructeur par défaut (sans paramètre) pour une structure. Les membres de la structure ne peuvent pas avoir d'initialiseurs. Un constructeur par défaut est toujours fourni pour initialiser les membres de la structure à leurs valeurs par défaut.

De l'C# specification sur MSDN:

11.3 Les différences de classe et struct

Structs diffèrent des classes de plusieurs façons importantes:

  • Structs sont les types de valeurs (section 11.3.1).
  • Tous les types de structure héritent implicitement de de la classe System.ValueType (section 11.3.2). L'affectation à une variable d'un type struct crée une copie de la valeur affectée (section 11.3.3).
  • La valeur par défaut d'un struct est la valeur produite par le réglage de tous les champs de type valeur à leur valeur par défaut et tous les champs de type référence à null (Section 11.3.4). Boxing et opérations de déballage sont utilisés pour convertir entre un type struct et objet (section 11.3.5).
  • La signification de ceci est différente pour structs (section 11.3.6).
  • Les déclarations de champ d'instance pour une structure ne doivent pas inclure d'initialiseurs variables (section 11.3.7).
  • Une structure n'est pas autorisée à déclarer un constructeur d'instance sans paramètre (section 11.3.8).
  • Une structure n'est pas autorisée à déclarer comme destructeur (section 11.3.9).