c#中struct和property的问题

问题描述 投票:31回答:6

在一个文件中我定义了一个公共结构

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'的返回值,因为它不是变量

如何更正语法?

c# struct
6个回答
38
投票

强烈建议避免使用可变结构。他们表现出各种令人惊讶的行为。

解决方案:使您的结构不可变。

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

48
投票

是的,这是绝对正确的。你看,当你获取My_va时,你正在获取一个值 - my_va当前值的副本。更改该值将没有任何好处,因为您将立即丢弃该副本。编译器阻止你编写代码,而代码却没有像它那样做。

一般来说,避免可变结构。他们是邪恶的。在这种情况下,您可以(例如)将mystruct更改为不可变,但使用如下方法:

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

然后将构造函数代码更改为:

My_va = My_va.WithStruct1(10);

...虽然在这种情况下,你应该写的更可能(假设你在构造函数中):

My_va = new mystruct(10, 0);

结构不仅应该是不可变的,它们在大多数代码库中都应该是非常罕见的,IMO。除了Noda Time,我几乎没有编写自己的自定义值类型。

最后,请学习.NET naming conventions并尝试遵循它们,即使是示例代码:)


2
投票

最简单的修复:将结构更改为类。


2
投票

我使用结构列表,并以不同的方式解决了这个问题。

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


1
投票

遗憾的是,在分配属性(即调用属性设置器)时,可能会错误地生成此错误。不可变结构仍然可以具有有效的属性设置器,只要属性设置器实际上不分配给结构中的任何字段。例如,

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

0
投票

值得注意的是,你可以通过以下方式克服这种行为:

  1. 按结构实现接口:Struct : IStruct
  2. 将struct声明为字段: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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.