81 votes

Comment initialiser struct?

Quel membre devrais-je implémenter dans ma structure arbitraire pour rendre possible l'affectation suivante:

 public struct MyStruct {
   String s;
   Int length;
}

MyStruct myStruct = new MyStruct { s = "Hello", length = 5 };

// Now, I want the following code to set the 's' to "Lol" and the
// length to 3 (length of "Lol"). The second part should be done
// automatically.
myStruct = "Lol"; // Or myStruct = String("Lol");
 

Comment cela devrait-il être fait?

124voto

Guffa Points 308133

Vous utilisez un opérateur implicite qui convertit la valeur de chaîne en une valeur de struct:

 public struct MyStruct {
  public string s;
  public int length;

  public static implicit operator MyStruct(string value) {
    return new MyStruct() { s = value, length = value.Length };
  }

}
 

Exemple:

 MyStruct myStruct = "Lol";
Console.WriteLine(myStruct.s);
Console.WriteLine(myStruct.length);
 

Sortie:

 Lol
3
 

11voto

supercat Points 25534

Les types de Structure devraient, dans la mesure du possible, soit la totalité de leur état encapsulé dans des champs publics qui peuvent être définies pour toutes les valeurs qui sont valables pendant leur type, ou d'autre se comportent comme une seule et même valeur qui ne peut parier réglé via le constructeur, d'usine, d'une méthode ou d'une autre par le passage d'une instance de la structure explicite ref paramètre pour l'un de ses méthodes publiques. Contrairement à ce que certains prétendent, il n'y a rien de mal avec une structure ayant des champs publics, si elle est censée représenter un ensemble de valeurs qui pourraient raisonnablement être manipulés individuellement ou passée autour d'un groupe (par exemple, les coordonnées d'un point). Historiquement, il y a eu des problèmes avec des structures qui ont la propriété publique des poseurs, et un désir d'éviter les champs publics (ce qui implique que les setters devrait être utilisé à la place) a conduit certains à suggérer que mutable structures devraient être évités, mais les champs n'ont pas les problèmes que les propriétés avaient. En effet, un exposé-champ struct est la représentation idéale pour un lâche collection de variables indépendantes, car il est juste un lâche collection de variables.

Dans votre exemple particulier, cependant, il semble que les deux champs de votre structure sont probablement pas censée être indépendante. Il y a trois façons struct pourrait raisonnablement être conçu:

  • Vous pourriez avoir le seul champ public par la chaîne, et ensuite une lecture seule "aide" propriété appelée length qui rendrait compte de sa longueur si la chaîne est non nulle, ou le retour à zéro si la chaîne est nulle.

  • Vous pourriez avoir la struct pas exposer les champs publics, les setters de propriété, ou de la mutation des méthodes, le contenu du champ--une chaîne privée--être spécifié dans le constructeur de l'objet. Comme ci-dessus, length serait une propriété qui ferait rapport à la longueur de la chaîne stockée.

  • Vous pourriez avoir la struct pas exposer les champs publics, les setters de propriété, ou de la mutation des méthodes, et ont deux champs: l'un pour la chaîne et une pour la longueur, à la fois de ce qui serait situé dans un constructeur qui prend une chaîne de caractères, les stocke, les mesures de sa longueur, et les magasins qui. Détermination de la longueur d'une chaîne est suffisamment rapide qu'il ne serait probablement pas la peine de calculer et de mettre en cache, mais il pourrait être utile de disposer d'une structure qui combine une chaîne et son GetHashCode de la valeur.

Il est important de prendre conscience d'un détail à l'égard de la troisième conception, cependant: si non thread-safe code provoque une instance de la structure à lire, tandis qu'un autre thread d'écriture pour elle, cela peut causer de la garantie en cas de création d'une structure d'une instance dont les valeurs de champ sont incompatibles. La résultante de comportements peuvent être un peu différents de ceux qui se produisent lorsque les classes sont utilisés dans les threads de la mode. Le code ayant rien à voir avec la sécurité doit être prudent de ne pas supposer que les champs de structure sera dans un état cohérent, puisque le code malveillant, même dans un "confiance totale" de l'environnement--peut facilement générer des structures dont l'état est incompatible si c'est ce qu'il veut faire.

PS - Si vous souhaitez permettre à votre structure pour être initialisé à l'aide d'une affectation à partir d'une chaîne, je vous recommande d'utiliser une conversion implicite de l'opérateur et de faire Length être une propriété en lecture seule qui retourne la longueur de la sous-chaîne de caractères en cas de non-nulle, ou zéro si la chaîne est nulle.

5voto

Scott Wisniewski Points 14420
  1. La "longueur" sera-t-elle toujours différente de la longueur réelle de "s"? Si la réponse est non, vous n'avez pas besoin de stocker la longueur, car les chaînes stockent déjà leur longueur et vous pouvez simplement appeler s.Length.

  2. Pour obtenir la syntaxe que vous avez demandée, vous pouvez implémenter un opérateur "implicite" comme ceci:

     static implicit operator MyStruct(string s) {
        return new MyStruct(...);
    }
     
  3. L'opérateur implicite fonctionnera, que vous rendiez votre structure mutable ou non.

2voto

Adam Spicer Points 1830

Ce n'est pas possible ... Votre structure peut avoir des méthodes et des propriétés ... pourquoi ne pas essayer

 
public struct MyStruct { 
  public string s;
  public int length { return s.Length; }
}
 

La réponse de Correction @ Guffa montre qu'il est possible ... plus d'infos ici: http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx

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