【问题标题】:Private parameterless constructor for the sake of the new property-based initialization用于新的基于属性的初始化的私有无参数构造函数
【发布时间】:2015-03-22 05:17:26
【问题描述】:

我在《深度 C#》一书中读到:

私有无参数构造函数用于新的基于属性的初始化。在下面的示例中,我们实际上可以完全删除公共构造函数,但是没有外部代码可以创建其他产品实例。

using System.Collections.Generic;

class Product
{
    public string Name { get; private set; }
    public decimal Price { get; private set; }

    public Product(string name, decimal price)
    {
        Name = name;
        Price = price;
    }

    Product() { }

    public static List<Product> GetSampleProducts()
    {
        return new List<Product>
        {
            new Product { Name = "West Side Story", Price = 9.99m },
            new Product { Name = "Assassins", Price = 14.99m },
            new Product { Name = "Frogs", Price = 13.99m },
            new Product { Name = "Sweeney Todd", Price = 10.99m }
        };
    }

    public override string ToString()
    {
        return string.Format("{0}: {1}", Name, Price);
    }
}

但如上所述,我可以创建新对象,例如

List<Product> ls = Product.GetSampleProducts();
            Product o = new Product("a",2);
            ls.Add(o);
            listBox1.DataSource = ls;

实际上没有私有无参数构造函数。有人能说明一下吗?

【问题讨论】:

  • @jon-skeet 如果您能对上述内容有所了解,那就太好了。

标签: c#


【解决方案1】:

你可以这样初始化对象:

 Product o = new Product( "a" , 2);

因为,它没有调用无参构造函数。为什么?

不带参数的构造函数称为无参数构造函数或默认构造函数 构造函数。每当一个对象被调用时,就会调用默认构造函数 通过使用 new 运算符和 没有参数被实例化 提供给新人。

上面的代码调用public Product(string name, decimal price)构造函数,正如你所见,它是public

毕竟,作者谈到了新的基于属性的初始化。这意味着:

Product product = new Product { Column1 = "col1", Column2 = "col2" };

这样初始化对象时,公共无参数构造函数会首先被调用。

而上面的代码只是一个语法糖

Product product = new Product(); // Compiler error in outside while default constructor is private
product.Column1 = "col1"; // Compiler error in outside while the set accessor is private
product.Column2 = "col2"; // Compiler error in outside while the set accessor is private

【讨论】:

  • 感谢法哈德。但是当我尝试了基于属性的初始化程序时。私有参数构造函数没有用,当我尝试将其公开时,它给出“无法在此上下文中使用属性或索引器,因为 set 访问器不可访问
  • 上面的评论指出,上面的代码设置器也应该是公共的。你说什么?
  • @hellowahab 一切正常。您已将 set 访问器设为私有。这意味着,它们在这个类的外部是只读的。
  • 是的,我知道,但是将访问器设置为私有也不允许基于属性的初始化。
  • @hellowahab 没错。虽然 set 访问器是私有的,但您不能在此类外部设置此属性的值。但是,您可以调用任何将设置值的公共构造函数。
【解决方案2】:

基于属性的初始化要求存在无参数构造函数。正如@farhad-jabiyev 已经正确指出基于属性的初始化,例如

Product product = new Product { Name = "West Side Story", Price = 9.99m };

只是代码的语法糖,如下所示:

Product product = new Product();
product.Name = "West Side Story";
product.Price = 9.99m;

如果你在问题提供的示例代码中注释了私有无参数构造函数,你会得到一个编译错误:

没有给出与“Product.Product(string, decimal)”的所需形式参数“name”相对应的参数

这意味着 C# 编译器会在分配属性值之前尝试调用无参数构造函数来创建 Product 类的实例。希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 2020-06-12
    • 2016-11-28
    • 2014-03-14
    • 2011-03-05
    • 2013-06-16
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多