我想将基类的实例用于初始化/实例化派生类,如下所示:
class B
{
//...
}
class D : B
{
bool DMember; // dummy example
//...
}
B b = new B();
// fill b members with values, do stuff
D d = (D)b.Clone(); // wrong, of course
d.DMember = true;
我们已经有了使用 B
克隆 MemberwiseClone
类的机制。
我实际上尝试在执行的某个时刻丰富一个类实例,而不对现有代码进行太多修改。
答案 0 :(得分:1)
C# 不像 C++ 那样支持隐式复制构造函数。您需要自己手动定义复制构造函数。
...是的,这既乏味又烦人。
像这样:
class PersonCommonData
{
public PersonCommonData(
Int32 personId,
String firstName,
String lastName,
Date dob
)
{
this.PersonId = personId;
this.FirstName = firstName;
this.LastName = lastName;
this.DoB = dob;
}
// Copy-constructor:
protected PersonCommonData( PersonCommonData copy )
: this(
personId: copy.PersonId,
firstName: copy.FirstName,
lastName: copy.LastName,
dob: copy.DoB
)
{
}
public Int32 PersonId { get; }
public String FirstName { get; }
public String LastName { get; }
public Date DoB { get; }
}
class EmployeePerson : PersonCommonData
{
public EmployeePerson( PersonCommonData copy, Int32 employeeId )
: base( copy )
{
this.EmployeeId = employeeId;
}
public Int32 EmployeeId { get; }
}
用法:
PersonCommonData common = GetCommonData( personId: 123 );
EmployeePerson e = new EmployeePerson( common, employeeId: 456 );
如果你在派生类中组合基础公共数据对象,那么事情就简单了:
(请注意,如果您的类是不可变的,这可能只是一个好主意,因为在对象图中拥有可变数据,甚至可能的可变数据很少是一个好主意 - 好消息是因为 C# 9.0 的 record
类型减少了很多乏味,但并没有消除它)。
class PersonCommonData
{
public PersonCommonData(
Int32 personId,
String firstName,
String lastName,
Date dob
)
{
this.PersonId = personId;
this.FirstName = firstName;
this.LastName = lastName;
this.DoB = dob;
}
public Int32 PersonId { get; }
public String FirstName { get; }
public String LastName { get; }
public Date DoB { get; }
}
class EmployeePerson
{
private readonly PersonCommonData common;
public EmployeePerson( PersonCommonData common, Int32 employeeId )
{
this.common = common ?? throw new ArgumentNullException(nameof(common));
this.EmployeeId = employeeId;
}
public Int32 EmployeeId { get; }
// Tedium: need to repeat every member as a property-forwarder:
public Int32 PersonId => this.common.PersonId;
public String FirstName => this.common.FirstName;
public String LastName => this.common.LastName;
public Date DoB => this.common.DoB;
}
record
类型和默认接口实现的 C# 9.0 中甚至更好...如果您只使用不可变数据,那么在 C# 9.0 中,您可以使用 record
类型,这样可以消除很多乏味的事情。不过我觉得它们最适合组合:
public record PersonCommonData(
Int32 PersonId,
String FirstName,
String LastName,
Date DoB
);
public interface IHasPersonCommonData
{
PersonCommonData Common { get; }
Int32 PersonId => this.Common.PersonId;
String FirstName => this.Common.FirstName;
String LastName => this.Common.LastName;
Date DoB => this.Common.DoB;
}
public interface IEmployeePerson : IHasPersonCommonData
{
Int32 EmployeeId { get; }
}
public record EmployeePerson(
PersonCommonData Common,
Int32 EmployeeId
) : IEmployeePerson;
public interface IStudentPerson : IHasPersonCommonData
{
Int32 StudentId { get; }
}
public partial StudentPerson( PersonCommonData Common, Int32 StudentId ) : IStudentPerson;
但是有一些限制 - C# 仍然不支持真正的 mixin(接口默认实现仅在通过接口访问类型时才有效,成员不会被继承boo)。