14

我一直在学习 C#,并想查看一些开源项目以查看一些好的编写代码。我在 sourceforge 上找到了一个名为 Todomoo 的项目,其中有一部分让我感到困惑:

public class Category {

    // Note properties
    private int id = 0;
    private string name = "";
    private Color colour = Color.Gray;

    /// <summary>
    /// Create a new category.
    /// </summary>
    public Category() { }

    /// <summary>
    /// Load a category from the database.
    /// </summary>
    /// <param name="Id">ID of the category</param>
    public Category(int id) : base() {
        Load(id);
    }

在这里,它base()在其中一个构造函数中使用,但该类不是派生类。那究竟是为了什么?

为什么是这样的语法base()而不是这样:

    public Category(int id) {
        base();
        Load(id);
    }
4

6 回答 6

17

但该类不是派生类

该类是派生类 - 它隐式继承自System.Object. 不过,尚不清楚为什么有人会base()为 调用构造函数System.Object:它也是隐式完成的。

就语法而言,我的猜测是 C# 采用了一种接近 C++ 初始值设定项列表的语法,而不是 Java 对基本构造函数的调用。

于 2012-08-08T14:46:34.550 回答
14

C# 中的每个类都是从System.Object Reference of Object in C#派生的类

于 2012-08-08T14:45:45.050 回答
3

要回答第一个问题,所有用户定义的类都至少继承自一个其他类(对象)。这意味着将默认构造函数定义为父构造函数几乎总是有效的(不仅当对象更直接地从其他没有可见默认构造函数的东西继承时)。但是,在这种情况下,它是多余的。如果基类的默认构造函数存在并且可以从子类访问,则将调用它,而无需您这么说。

其次,与方法覆盖不同,选择是否以及在何处扩展基类构造函数的功能不是一种选择。必须调用基类的构造函数来初始化父级中的数据成员(您可能在子级中访问也可能无法访问),这必须在调用子级构造函数之前发生(如果子级需要任何父级结构存在)。因此,它们不允许您在任何地方调用基类构造函数,而是强制您定义在使用此特定子构造函数时要调用的基类构造函数,并且运行时将处理何时何地。

于 2012-08-08T14:50:06.520 回答
2

您不能在构造函数代码中的某处调用构造函数,因为语言对此进行了限制。就中间语言而言,构造函数只是另一个方法调用。

于 2012-08-08T14:47:36.343 回答
2

正如其他人指出的那样,所有类都派生自System.Object.

在您的具体示例中,base()调用System.Object. 这实际上没有任何意义,因为基类的默认构造函数总是被调用,即使base()没有指定。

例如下面的代码

public class Foo
{
    public Foo()
    {
        Console.WriteLine("Foo");
    }
}

public class Foo2 : Foo
{
    public Foo2()
    {
        Console.WriteLine("Foo2");
    }
}

public class Program
{
    private static void Main(string[] args)
    {
        Foo2 d = new Foo2();

        Console.ReadKey();
    }
}

印刷

Foo2

于 2012-08-08T14:52:46.840 回答
1

它是一个外部构造函数,它在 Category 构造函数之前构造它,当你这样做base();时不会发生任何事情,因为它是一个构造函数并返回一些东西,并this = new base()会导致错误

于 2012-08-08T14:47:28.433 回答