简体   繁体   中英

Problem with struct and property in c#

in a file I defined a public struct

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

In another I tried to do this:

class Test
{
    mystruct my_va;

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

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

Intellisense recognizes My_va.struct1 but compiler says

Error 1 Cannot modify the return value of 'TEST.mystruct' because it is not a variable

How to correct the syntax ?

Yup, it's absolutely right. You see, when you fetch My_va , you're fetching a value - a copy of the current value of my_va . Changing that value would have no benefit, because you'd be immediately discarding the copy. The compiler is stopping you from writing code which doesn't do what it looks like it does.

In general, avoid mutable structs. They're evil. In this case, you could (for example) change mystruct to be immutable, but with a method like this:

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

then change your constructor code to:

My_va = My_va.WithStruct1(10);

... although in this case it's far more likely (given that you're in a constructor) that you should be writing:

My_va = new mystruct(10, 0);

Not only should structs be immutable, they should be pretty rare in most codebases, IMO. Other than for Noda Time , I've hardly ever written my own custom values types.

Finally, please learn the .NET naming conventions and try to follow them, even for sample code :)

It is highly recommended to avoid mutable structs. They exhibit all sorts of surprising behaviour.

Solution: Make your struct immutable.

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

I work with a list of structs, and solved this in a different way.

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

Now when i want to set a value i code like this :

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

The code looks a bit strange perhaps, but it resolves the issue . It solves the problem that a struct cannot be directly assigned a single value, but can be a copy of a similar type. solving error 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

最简单的解决方法:将结构更改为类。

Unfortunately this error can be incorrectly generated when assigning to a property (ie invoking a property setter). An immutable struct can still have a valid property setter, as long as the property setter doesn't actually assign to any fields in the struct. For example,

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
    }
}

Worth noting, that you can overcome this behavior by:

  1. Implementing interface by struct: Struct : IStruct
  2. Declare struct as field: Struct strExplicitly;

Example:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM