web-dev-qa-db-fra.com

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?

53
Yippie-Ki-Yay

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
90
Guffa

Les types de structure doivent, chaque fois que cela est possible, soit avoir leur état encapsulé dans des champs publics pouvant être indépendamment définis sur des valeurs valides pour leur type respectif, soit se comporter comme une seule valeur unifiée pouvant uniquement être définie via le constructeur, la fabrique , méthode ou bien en passant une instance de la structure sous la forme d'un paramètre explicite ref à l'une de ses méthodes publiques. Contrairement à ce que certaines personnes prétendent, rien ne cloche dans une structure ayant des champs publics, si elle est supposée représenter un ensemble de valeurs qui peuvent être manipulées de manière raisonnable soit individuellement, soit transmises en tant que groupe (par exemple, les coordonnées d’un point). Historiquement, il y a eu des problèmes avec les structures dotées de propriétaires de propriétés publiques, et le désir d'éviter les champs publics (ce qui implique que les propriétaires doivent être utilisés à la place) a amené certaines personnes à suggérer que les structures mutables soient complètement évitées, mais les champs n'ont pas le même potentiel. problèmes que les propriétés avaient. En effet, une structure de champ exposé est la représentation idéale pour une collection lâche de variables indépendantes, puisqu'elle n'est qu'une collection lâche de variables.

Dans votre exemple particulier, cependant, il apparaît que les deux champs de votre structure ne sont probablement pas supposés être indépendants. Votre structure peut être raisonnablement conçue de trois manières:

  • Vous pourriez avoir le seul champ public qui soit la chaîne, puis une propriété "helper" en lecture seule appelée length qui indiquerait sa longueur si la chaîne est non nulle ou la valeur 0 si la chaîne est nulle .

  • Vous pouvez demander à la structure de ne pas exposer de champs publics, de paramètres de propriété ou de méthodes de mutation, et de spécifier le contenu du seul champ, une chaîne privée, dans le constructeur de l'objet. Comme ci-dessus, length serait une propriété qui indiquerait la longueur de la chaîne stockée.

  • Vous pouvez demander à la structure de ne pas exposer de champs publics, de paramètres de propriété ou de méthodes de mutation, et d’avoir deux champs privés: un pour la chaîne et un pour la longueur, les deux étant définis dans un constructeur qui prend une chaîne, la stocke. , mesure sa longueur et le stocke. Déterminer la longueur d'une chaîne est suffisamment rapide pour qu'il ne soit probablement pas intéressant de la calculer et de la mettre en cache, mais il pourrait être utile de disposer d'une structure combinant une chaîne et sa valeur GetHashCode.

Cependant, il est important de connaître un détail relatif à la troisième conception: si un code non threadsafe provoque la lecture d’une instance de la structure pendant l’écriture d’un autre thread, cela peut entraîner la création accidentelle d’une instance de struct dont les valeurs de champ sont incohérentes. Les comportements résultants peuvent être légèrement différents de ceux qui se produisent lorsque les classes sont utilisées de manière non threadsafe. Tout code ayant quelque chose à voir avec la sécurité doit faire attention à ne pas supposer que les champs de structure seront dans un état cohérent, car un code malveillant - même dans un environnement de "confiance totale" - peut facilement générer des structs dont l'état est incohérent si tel est le cas. il veut faire.

PS - Si vous souhaitez autoriser l'initialisation de votre structure à l'aide d'une affectation à partir d'une chaîne, je suggérerais d'utiliser un opérateur de conversion implicite et de rendre Length être une propriété en lecture seule qui renvoie la longueur de la chaîne sous-jacente si non-null, ou zéro si la chaîne est null.

9
supercat
  1. La "longueur" sera-t-elle toujours différente de la longueur réelle de "s"? Si la réponse est non, alors 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.

5
Scott Wisniewski

Votre struct 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; }
}

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

1
Adam Spicer