为什么C#实例构造函数与返回的类型具有不同的名称?

时间:2014-07-21 20:23:23

标签: c# constructor instantiation

我有时会在C#代码中看到:

正在创建的实例,然后调用与该类型的构造函数不同的构造函数。

例如:

Person somebody = new Member();

这会出现哪些可能的情况,为什么会这样?

(我认为这与调用基类构造函数有关,但我无法编译)

4 个答案:

答案 0 :(得分:3)

成员继承自Person或Person是一个命名不佳的接口,而Member会实现它:

有关继承的更多信息: http://msdn.microsoft.com/en-gb/library/ms173149(v=vs.80).aspx http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)

有关接口的更多信息: http://msdn.microsoft.com/en-us/library/ms173156.aspx http://en.wikipedia.org/wiki/Protocol_(object-oriented_programming)

您可以使用继承来定义以下内容:

public class Person
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
}

public class Adult : Person
{
    public string Workplace { get; set; }
}

public class Child : Person
{
    public List<string> Toys { get; set; }
}

然后,如果您创建Adult(Adult a = new Adult();)实例,您将可以访问Name,DateOfBirth和Workplace属性。与孩子一样,您将拥有玩具属性。

此外,您可以存储包含成人和儿童的人员列表:

List<Person> people = new List<Person>();
people.Add(new Adult() { Name = "Adult", DateOfBirth = DateTime.Now, Workplace = "Microsoft" });
people.Add(new Child() { Name = "Child", DateOfBirth = DateTime.Now, Toys = new List<string> { "Car", "Train" } });

然后你可以通过每个印刷出名称和出生日期:

foreach(Person p in people)
{
    Console.WriteLine(p.Name + ", " + p.DateOfBirth.ToString("dd/MMM/yy"));
    if(p is Child)
    {
        Console.WriteLine(p.Name + " has the following toys: " + string.Join(", ", ((Child)p).Toys));
    }
    else if(p is Adult)
    {
        Console.WriteLine(p.Name + " works at " + ((Adult)p).Workplace;
    }
}

接口基本上定义了一个契约(即实现IPerson的对象将为其方法提供实现)。它就像一个以太网卡:它们如何与网络通信有一个标准,但它们如何在内部工作取决于制造商,只要它们提供预期的行为即可。接口不能包含任何逻辑或存储任何数据,它们只是宣传实现该接口的内容。

public interface IPerson
{
    string Name { get; set; }
    DateTime DateOfBirth { get; set; }
}

public class Adult : IPerson
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Workplace { get; set; }
}

public class Child : IPerson
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public List<string> Toys { get; set; }
}

还有抽象类提供了接口的一些功能,但可以实现一些逻辑。所有这一切中唯一需要注意的是,类只能从单个类派生(即从其继承),尽管该类可以从另一个类继承。但是,您可以实现多个接口。

答案 1 :(得分:2)

如果Person是基类Member

,则此选项有效

同样,这也是有效的:

Object o = new Member();

答案 2 :(得分:1)

你的问题不是关于构造函数的问题。这完全是关于隐式转化。在您的声明中:

Person somebody = new Member();

=运算符的右侧显然具有(编译时)类型Member。但是变量somebody具有(编译时)类型Person。只有存在从MemberPerson的隐式转换时,这才合法。然后代码真的像Person somebody = (Person)(new Member());,除了“强制转换”是不可见的。

现在,最常见的隐式转换是从class到其(直接或间接)基类的引用转换,或者它实现的接口。

隐式转换有一些不同,从structenum到其基类或接口的装箱转换。

还有一些用户定义的隐式转换,就像一种方法(用implicit operator编写)。

还有更多隐式转换,例如从值类型VNullable<>版本,通常写为V?,但如果Person则会很奇怪}只是using的{​​{1}}别名,所以这个在你的例子中是不现实的。在这个例子中很少相关的另一个是“扩大”转换,例如, Member?int

阅读C#语言规范,了解有关转换存在的更多信息。

答案 3 :(得分:0)

Member类可能看起来像这样......

public class Member : Person {}

Member来自Person