【问题标题】:Class with nested struct as a property doesn't work [duplicate]具有嵌套结构作为属性的类不起作用[重复]
【发布时间】:2014-10-28 09:14:30
【问题描述】:

为什么下面的代码不起作用? 如果我将h 从属性更改为字段,它会起作用! 或者,如果我将 FileHeaderstruct 更改为 class,它会起作用! 我只是在寻找为什么它不起作用的答案。

public class MyFile
{
    public struct FileHeader
    {
        public List<string> ColNames
        {
            get;
            set;
        }

        public void setColNames()
        {
            ColNames = new List<string>();
            ColNames.Add("address");
        }
    }

    public FileHeader h
    {
        get;
        set;
    }
}

public class Program
{
    static void Main(string[] args)
    {
        MyFile o = new MyFile();
        o.h.setColNames();

        Console.WriteLine(o.h.ColNames[0]); // <- Doesn't work! No elements

        string line = System.Console.ReadLine();
    }
}

【问题讨论】:

  • 可变结构是邪恶的。现在您知道原因之一了。
  • "...不起作用"; “... 有用!” - 这对帮助我们帮助您并没有真正的帮助。你是什​​么意思不起作用?编译时错误?运行时错误?结果不正确?我们可以猜测,因为结构有一些特定的特征可以很容易地找出你在抱怨什么。但说真的……帮帮我们吧。

标签: c# properties struct


【解决方案1】:

这一行:

o.h.setColNames();

相当于:

FileHeader tmp = o.h;
tmp.setColNames();

因为FileHeader 是一个结构,所以tmp 的值是o 中字段值的副本。修改tmp 不会改变o.h

我建议:

  • 除非创建自然(小)值类型,否则不要创建自定义结构
  • 创建的任何自定义结构都应该是不可变的。到时候就更难犯这种错误了
  • 遵循 .NET 命名约定 - h 的属性和 setColNames 的方法都违反了这一点
  • 避免嵌套类型,除非有显着的好处。这与您的实际问题无关,但它会使各种事情变得更加棘手。

【讨论】:

  • +1。附加建议:注意警告 - 应该有一个导致问题的行。
【解决方案2】:

属性实际上是从您那里抽象出来的方法。它最终成为一个名为 Set.. 的方法和一个名为 Get... 的方法,它检索隐藏的支持变量或设置隐藏的支持变量。

结构是值类型。当您将值类型传递给方法时,它会复制它们。例如。 o.h.setColNames 正在添加到副本中,而不是 o.h 支持字段的实际实例。

如果你做了一个类似的属性

public int SomeInteger { get;放; }

它也是一个值类型,但它之所以有效,是因为 setter 正在设置实际实例,而 getter 会返回一个匹配的副本。

但是在您的代码中,您使用类包装了您的结构,因此您总是得到一个未调用 setColNames 的副本。

这是我在此处发布的一些脏代码,但它演示了如何通过让结构具有对其父类的引用来保留此设计并设置新副本。

    public class MyFile
{
    public struct FileHeader
    {
        internal MyFile _parent;
        public List<string> ColNames
        {
            get;
            set;
        }

        public void setColNames()
        {
            ColNames = new List<string>();
            ColNames.Add("address");
            _parent._h = this;
        }
    }

    private FileHeader _h = new FileHeader();
    public FileHeader h
    {
        get { return _h; }
    }  

    public MyFile()
    {
        _h._parent = this;
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyFile o = new MyFile();
        o.h.setColNames();
        Console.WriteLine(o.h.ColNames[0]);

        string line = System.Console.ReadLine();
    }
}

【讨论】:

  • 这段代码很糟糕,只是一个演示。这是一个非常糟糕的设计,因为每次调用 setColNames 时它都会将旧结构转储到 GC 上。
猜你喜欢
  • 2014-12-28
  • 2023-03-31
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-24
  • 2018-07-05
相关资源
最近更新 更多