Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中创建只读对象属性?_C#_Asp.net_Properties_Readonly - Fatal编程技术网

如何在C#中创建只读对象属性?

如何在C#中创建只读对象属性?,c#,asp.net,properties,readonly,C#,Asp.net,Properties,Readonly,如下所示,用户可以更改只读产品字段/属性: class Program { static void Main(string[] args) { var product = Product.Create("Orange"); var order = Order.Create(product); order.Product.Name = "Banana"; // Main method s

如下所示,用户可以更改只读产品字段/属性:

class Program
    {
        static void Main(string[] args)
        {
            var product = Product.Create("Orange");
            var order = Order.Create(product);
            order.Product.Name = "Banana"; // Main method shouldn't be able to change any property of product!
        }
    }

    public class Order
    {
        public Order(Product product)
        {
            this.Product = product;
        }

        public readonly Product Product;

        public static Order Create(Product product)
        {
            return new Order (product);
        }
    }

    public class Product
    {
        private Product(){}

        public string Name { get; set; }

        public static Product Create(string name)
        {
            return new Product { Name = name };
        }
    }
我认为这很基本,但似乎不是这样

如何在C#?中创建只读对象属性或字段


谢谢,

关键字
readonly
阻止您将新实例放入该字段

它不会神奇地使字段中的任何对象不可变。
如果你写作,你希望发生什么

readonly Product x = Product.Create();

Product y;
y = x;
y.Name = "Changed!";

如果您想要一个不可变对象,则需要通过删除所有公共setter使类本身不可变。

您需要使Product private set的Name属性:

public class Product
{
    private Product(){}

    public string Name { get; private set; }

    public static Product Create(string name)
    {
        return new Product { Name = name };
    }
}

只读字段总是可以在构造函数中修改。如果试图在其他位置编辑该字段,则会出现编译器错误。

readonly关键字表示只能在构造函数中设置该字段&该值不能更改

如果该值是引用类型,则不会使对象为只读


如果要使属性为只读,只需省略setter。

您看到的问题是将
readonly
修饰符与您认为的只读属性混淆。
readonly
修饰符确保只能通过初始化或构造函数将字段分配给,例如这里有
readonly
的有效用法:

public class MyClass
{
  private readonly int age = 27; // Valid, initialisation.
}

public class MyClass
{
  private readonly int age;

  public MyClass() 
  {
    age = 27; // Valid, construction.
  }
}

public class MyClass
{
  private readonly int age;

  public int Age { get { return age; } set { age = value; } } // Invalid, it's a readonly field.
}
order.Product = Product.Create("Apple") // <- not allowed because Product field is readonly
order.Product.Name = "Apple" // <- allowed because Name is not readonly field or private property

您发现,
Person
类本身是可变的,这意味着尽管字段
Order.Product
是只读的,
Person
的内部结构不是只读的。为此,如果要创建只读属性,可能需要将类型创建为不可变的,因为其内部结构/值不能更改。

要更好地演示只读属性,请执行以下操作:

public class MyClass
{
  private readonly int age = 27; // Valid, initialisation.
}

public class MyClass
{
  private readonly int age;

  public MyClass() 
  {
    age = 27; // Valid, construction.
  }
}

public class MyClass
{
  private readonly int age;

  public int Age { get { return age; } set { age = value; } } // Invalid, it's a readonly field.
}
order.Product = Product.Create("Apple") // <- not allowed because Product field is readonly
order.Product.Name = "Apple" // <- allowed because Name is not readonly field or private property
当然,这个解决方案的问题是:

new Product { Name = "Orange" } // <- not allowed if called from outside Product class
它们之间唯一的区别是:

order.Product.Name = "Apple" // <- not allowed
Product product = new Product { Name = "Orange" } // not allowed in solution #1 when called from outside Product, allowed in solution #2
product.Name = "Apple" // <- not allowed in solution #1 but allowed in solution #2

order.Product.Name=“苹果”//Related:这不是他的问题,尽管一开始可能并不明显
Product
是只读的,他的问题是为什么他以后可以更改
Product.Name
。啊,是的,我错过了主要的属性更改。我只在Order构造函数中看到它的初始化。在这种情况下,+1在SLaks上回答!