web-dev-qa-db-fra.com

Problème avec struct et property en c #

dans un fichier j'ai défini une structure publique

public struct mystruct
{
    public Double struct1;
    public Decimal struct2;
}

Dans un autre, j'ai essayé de faire ceci:

class Test
{
    mystruct my_va;

    public mystruct my_va
    {
        get { return my_va; }
        set { my_va = value; }
    }

    public Test()
    {
        my_va.struct1 = 10;
    }
}

Intellisense reconnaît My_va.struct1 mais le compilateur dit

Erreur 1 Impossible de modifier la valeur de retour de 'TEST.mystruct' car ce n'est pas un variable

Comment corriger la syntaxe?

31
user310291

Il est fortement recommandé d'éviter les structures mutables. Ils présentent toutes sortes de comportements surprenants.

Solution: Rendez votre structure immuable.

public struct MyStruct
{
    public readonly double Value1;
    public readonly decimal Value2;

    public MyStruct(double value1, decimal value2)
    {
        this.Value1 = value1;
        this.Value2 = value2;
    }
}

Usage:

class Test
{
    private MyStruct myStruct;

    public Test()
    {
        myStruct = new MyStruct(10, 42);
    }

    public MyStruct MyStruct
    {
        get { return myStruct; }
        set { myStruct = value; }
    }
}
38
dtb

Ouais, c'est absolument vrai. Vous voyez, lorsque vous fetchMy_va, vous récupérez une valeur - une copie de la valeur actuelle de my_va. La modification de cette valeur n’aurait aucun avantage, car vous perdriez immédiatement la copie. Le compilateur vous empêche d'écrire du code qui ne fait pas ce à quoi il ressemble.

En général, évitez les structures mutables. Ils sont diaboliques. Dans ce cas, vous pouvez (par exemple) changer mystruct pour qu'il soit immuable, mais avec une méthode comme celle-ci:

public mystruct WithStruct1(double newValue)
{
    return new mystruct(newValue, struct2);
}

puis changez votre code constructeur en:

My_va = My_va.WithStruct1(10);

... bien que dans ce cas, il est beaucoup plus probable (étant donné que vous êtes dans un constructeur) que vous deviez écrire:

My_va = new mystruct(10, 0);

Non seulement les structures doivent être immuables, mais elles doivent être assez rares dans la plupart des bases de code, IMO. Autre que pour Noda Time , je n’ai presque jamais écrit mes propres types de valeurs personnalisées.

Enfin, veuillez apprendre les conventions de dénomination .NET et essayer de les suivre, même pour un exemple de code :)

48
Jon Skeet

Solution la plus simple: changez la structure en classe.

3
Doug

Je travaille avec une liste de structures et je l'ai résolu d'une manière différente.

struct Pixel
{ Public int X;
  Public int C;
}
List<Pixel> PixelList = new List<Pixel>
TempPixel = new Pixel();

Maintenant, quand je veux définir une valeur, je code comme ceci:

TempPixel = PixelList[i];
TempPixel.X= 23;  // set some value
PixelList[i] = TempPixel

Le code semble un peu étrange peut-être, mais il résout le problème . Il résout le problème selon lequel une structure ne peut pas être affectée directement à une valeur unique, mais peut être une copie d'un type similaire . Résolution de l'erreur CS1612: 

https://msdn.Microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k%28CS1612%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV2.0%22%. ; k% 28DevLang-CSHARP% 29 & rd = true

2
user613326

Malheureusement, cette erreur peut être générée incorrectement lors de l’affectation d’une propriété (c’est-à-dire lorsqu’un configurateur de propriétés) Une structure immuable peut toujours avoir un configurateur de propriété valide, à condition que celui-ci n'affecte aucun champ de la structure. Par exemple, 

public struct Relay
{
    public Relay(Func<string> getText, Action<string> setText)
    {
        this.GetText = getText;
        this.SetText = setText;
    }
    private readonly Func<string> GetText;
    private readonly Action<string> SetText;

    public string Text {
        get { return this.GetText(); }
        set { this.SetText(value); }
    }
}

class Example
{
    private Relay Relay {
        get { return new Relay(() => this.text, t => { this.text = t; }); }
    }

    private string text;


    public Method()
    {
        var r = new Relay();
        r.Text = "hello"; // not a compile error (although there is a null reference)

        // Inappropriately generates a compiler error
        this.Relay.Text = "hello";

        r = this.Relay;
        r.Text = "hello"; // OK
    }
}
1
sjb-sjb

À noter que vous pouvez surmonter ce problème en:

  1. Implémentation d'interface par struct: Struct : IStruct
  2. Déclarer la struct comme champ: Struct strExplicitly;

Exemple:

public interface IStruct
{
    int Age { get; set; }
}

public struct Struct : IStruct
{
    public int Age { get; set; }
}

public class Test
{
    IStruct strInterface { get; set; }
    Struct strExplicitly;

    public Test()
    {
        strInterface = new Struct();
        strExplicitly = new Struct();
    }

    public void ChangeAge()
    {
        strInterface.Age = 2;
        strExplicitly.Age = 2;
    }
}
0
Slava Utesinov