c# - 设置一个匿名类型的只读属性

标签 c# .net

我最近在 C# 中遇到了一些相当令人困惑的事情。在我们的代码库中,我们有一个 TreeNode 类。在更改一些代码时,我发现无法将变量分配给 Nodes 属性。仔细检查后,很明显该属性是只读的,并且这种行为是可以预料的。

奇怪的是,我们的代码库在此之前一直依赖于将一些匿名类型分配给 Nodes 属性,并且可以完美地编译和运行。

总结一下:为什么 AddSomeNodes 中的赋值首先起作用?

using System.Collections.Generic;

namespace ReadOnlyProperty
{
    public class TreeNode
    {
        private readonly IList<TreeNode> _nodes = new List<TreeNode>();

        public IList<TreeNode> Nodes
        {
            get { return _nodes;  }
        }
    }

    public class TreeBuilder
    {
        public IEnumerable<TreeNode> AddSomeNodes()
        {
            yield return new TreeNode
             {
                Nodes = { new TreeNode() }
             };
        }

        public IEnumerable<TreeNode> AddSomeOtherNodes()
        {
            var someNodes = new List<TreeNode>();

            yield return new TreeNode
             {
                Nodes = someNodes
             };
        }
    }
}

最佳答案

AddSomeNodes没有创建 List<TreeNode> 的实例因为该语法是一个集合初始化器(因此它没有分配给 Nodes,这意味着它不会破坏 readonly 契约),编译器实际上将集合初始化器转换为对 .Add 的调用。 .

AddSomeOtherNodes call 实际上尝试重新分配值,但它是 readonly .这也是对象初始化器语法,它转化为简单的属性调用。此属性没有 setter,因此该调用会产生编译器错误。尝试添加设置只读值的 setter 将生成另一个编译器错误,因为它被标记为 readonly。 .

From MSDN :

By using a collection initializer you do not have to specify multiple calls to the Add method of the class in your source code; the compiler adds the calls.

另外,澄清一下,您的代码中没有匿名类型在起作用——它都是初始化语法。


与您的问题无关,但属于同一领域。

有趣的是,Nodes = { new TreeNode() }语法不适用于本地成员,它似乎只在嵌套在对象初始值设定项中或在对象分配期间有效:

List<int> numbers = { 1, 2, 3, 4 }; // This isn't valid.
List<int> numbers = new List<int> { 1, 2, 3, 4 }; // Valid.

// This is valid, but will NullReferenceException on Numbers
// if NumberContainer doesn't "new" the list internally.
var container = new NumberContainer()  
{
    Numbers = { 1, 2, 3, 4 }
};

MSDN 文档似乎对此没有任何说明。

关于c# - 设置一个匿名类型的只读属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11415162/

相关文章:

C# 正则表达式从输入中提取组

c# - 为什么不能将 new[] {AnonymousType, AnonymousType} 强制转换为 IEnumerable?

.net - 如何使用 .NET XML API 删除 xmlns 属性

asp.net - 在屏幕键盘上调出大写的文本输入

在 PowerShell 中调用构造函数的 .NET 语法

c# - 将 List<Point> 存储在字符串中并解析回来的最佳方法

c# - GraphicsPath 和 DrawPath - 删除相交线

c# - 如何使用 LINQ 从列表中获取逗号分隔的值列表?

c# - 如何在 Windows Azure Web Apps 中发布和使用字体?

.net - 将 DataMember 添加到 WCF 中的现有 DataContract