64 votes

Automatique des Propriétés et des Structures Ne se Mélangent pas?

Coups de pied autour de quelques petites structures tout en répondant à ce post, je suis tombé sur la suite à l'improviste:

La structure suivante, à l'aide d'un champ int est parfaitement légal:

struct MyStruct
{ 
    public MyStruct ( int size ) 
    { 
        this.Size = size; // <-- Legal assignment.
    } 

    public int Size; 
}

Cependant, la structure suivante, à l'aide d'un système automatique de propriété ne compile pas:

struct MyStruct
{ 
    public MyStruct ( int size ) 
    { 
        this.Size = size; // <-- Compile-Time Error!
    } 

    public int Size{get; set;}
}

L'erreur renvoyée est "Le" il "de l'objet ne peut pas être utilisé avant que l'ensemble de ses champs sont affectés". Je sais que c'est la procédure standard pour une structure (struct): le champ de stockage pour n'importe quelle propriété doit être attribué directement (et non par la propriété de l'accesseur set) à partir de l'intérieur de la structure du constructeur.

Une solution est d'utiliser un accord explicite de champ:

struct MyStruct
{ 
    public MyStruct(int size)
    {
        _size = size;
    }

    private int _size;

    public int Size
    {
        get { return _size; }
        set { _size = value; }
    }
}

(Notez que VB.NET n'aurait pas ce problème, parce que dans VB.NET tous les champs sont automatiquement initialisées à 0/null/false lors de la première création.)

Cela semble être un malheureux limitation lors de l'utilisation automatique de propriétés avec les structures en C#. La pensée conceptuelle, je me demandais si ce ne serait pas un bon endroit pour qu'il y ait une exception qui permet à l'ensemble de propriétés accesseur pour être appelée à l'intérieur d'une structure du constructeur, au moins pour une automatique des biens?

C'est un problème mineur, presque un bord-cas, mais je me demandais ce que les autres pensaient à ce sujet...

81voto

Marc Gravell Points 482669

Vous avez besoin d'appeler le constructeur par défaut pour que cela fonctionne:

public MyStruct(int size) : this()
{
    Size = size;
}

Un plus grand problème ici est que vous avez une mutable struct. C'est jamais une bonne idée. Je voudrais faire:

public int Size {get; private set;}

Pas techniquement immuable, mais assez proche.

11voto

Stormenet Points 8695

Vous pouvez résoudre ce problème en appelant d'abord le constructeur par défaut:

    struct MyStruct {
        public MyStruct(int size)
            : this() {
            this.Size = size; // <-- now works
        }

        public int Size { get; set; }
    }

8voto

Daniel Fortunov Points 12044

Un autre obscur de travail autour de ce problème est repéré dans le temporaire Tuple de la classe dans le Managed Extensibility Framework (par Krzysztof Koźmic):

public struct TempTuple<TFirst, TSecond>
{
    public TempTuple(TFirst first, TSecond second)
    {
        this = new TempTuple<TFirst, TSecond>(); // Kung fu!
        this.First = first;
        this.Second = second;
    }

    public TFirst First { get; private set; }
    public TSecond Second { get; private set; }

(L'intégralité du code source à partir de Codeplex: Tuple.cs)

Je note également que la documentation pour CS0188 a été mis à jour pour ajouter:

Si vous voyez ce message d'erreur lorsque vous essayez d' initialiser une propriété dans une struct constructeur, la solution est de changer le constructeur paramètre pour spécifier le champ de stockage au lieu de la la propriété elle-même. Auto-mise en œuvre les propriétés doivent être évités dans les les structures parce qu'ils n'ont pas de sauvegarde champ et, par conséquent, ne peut pas être initialisé en aucune façon de la constructeur.

Donc je prends ça pour dire que le guide officiel est d'utiliser de vieux-propriétés de style dans votre structs lorsque vous exécutez dans ce problème, qui est probablement moins obscur (et plus readible) que les deux autres alternatives explorées jusqu'à présent.

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