web-dev-qa-db-ja.com

C#の構造体とプロパティの問題

ファイル内でパブリック構造体を定義しました

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

別の私はこれをやろうとしました:

class Test
{
    mystruct my_va;

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

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

IntellisenseはMy_va.struct1を認識しますが、コンパイラは言います

エラー1 'TEST.mystruct'の戻り値は変数ではないため変更できません

構文を修正するには?

33
user310291

可変構造体を避けることを強くお勧めします。彼らはあらゆる種類の驚くべき行動を示します。

解決策:構造体を不変にします。

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

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

使用法:

class Test
{
    private MyStruct myStruct;

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

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

うん、それは絶対に正しい。ご覧のとおり、fetchMy_vaの場合、値をフェッチしています-my_vaの現在の値のコピーです。その値を変更しても、すぐにコピーが破棄されるため、メリットはありません。コンパイラーは、見た目どおりに動作しないコードの作成を阻止しています。

一般的に、可変構造体は避けてください。彼らは悪です。この場合、(たとえば)mystructを不変に変更できますが、次のようなメソッドを使用します。

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

次に、コンストラクターコードを次のように変更します。

My_va = My_va.WithStruct1(10);

...thisの場合、あなたが書くべきである可能性が非常に高いです(あなたがコンストラクタにいると仮定すると):

My_va = new mystruct(10, 0);

構造体は不変であるだけでなく、ほとんどのコードベース、IMOではかなりまれです。 Noda Time の場合を除き、独自のカスタム値タイプを記述することはほとんどありません。

最後に、 。NET命名規則 を学習し、サンプルコードであってもそれらに従うようにしてください:)

48
Jon Skeet

私は構造体のリストを操作し、これを別の方法で解決しました。

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

今、私はこのようなコードを値を設定したいとき:

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

コードはおそらく少し奇妙に見えますが、問題は解決します。構造体に単一の値を直接割り当てることはできませんが、同様の型のコピーを割り当てることができるという問題を解決します。エラー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 %29; k%28DevLang-CSHARP%29&rd = true

3
user613326

最も簡単な修正:構造体をクラスに変更します。

2
Doug

残念ながら、このエラーは、プロパティに割り当てる(つまり、プロパティセッターを呼び出す)ときに誤って生成される可能性があります。プロパティセッターが実際に構造体のフィールドに割り当てない限り、不変の構造体は有効なプロパティセッターを持つことができます。例えば、

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

次の方法でこの動作を克服できることに注意してください。

  1. 構造体によるインターフェイスの実装:Struct : IStruct
  2. 構造体をフィールドとして宣言:Struct strExplicitly;

例:

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