使用嵌套结构作为属性的类;不起作用
本文关键字:不起作用 属性 嵌套 结构 | 更新日期: 2023-09-27 18:20:36
为什么以下代码不起作用?如果我将h
从属性更改为字段,它会起作用!或者,如果我将FileHeader
从struct
更改为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();
}
}
此行:
o.h.setColNames();
相当于:
FileHeader tmp = o.h;
tmp.setColNames();
因为FileHeader
是一个结构,所以tmp
的值是o
中字段值的副本。修改tmp
不会更改o.h
。
我建议:
- 除非创建自然(小)值类型,否则不会创建自定义结构
- 所做创建的任何自定义结构都应该是不可变的。在这一点上,更难犯这种错误
- 遵循.NET命名约定-
h
的属性和setColNames
的方法都违反了 - 除非有显著的好处,否则应避免嵌套类型。这与你的实际问题无关,但它可能会使各种事情变得更棘手
属性实际上是从您那里抽象出来的方法。它最终成为一个名为Set的方法。。以及一个名为Get。。。它检索一个隐藏的后备变量或设置一个隐藏后备变量。
结构是值类型。当您将值类型传递给方法时,它会复制它们。例如,o.h.setColNames正在添加到副本中,而不是o.h的backing字段的实际实例。
如果你做了一个像这样的房产
public int SomeInteger{get;set;}
它也是一种值类型,但它之所以有效,是因为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();
}
}