我在C#中有一个抽象类:
public abstract class DataSeed {
private Context _context;
private IReadOnlyList<String> _languages = new List<String> { "en", "fr" };
private const String DRIVE = "http://mydriveurl";
}
仅与派生类共享这3个字段的最佳方法是什么:
public MyDataSeed : DataSeed {
}
我应该使用protected,protected并将它们转换为属性等吗?
请注意:
答案 0 :(得分:2)
我建议这样的事情:
public abstract class DataSeed {
// const, but can be used in any descendant class
protected const String DRIVE = "http://mydriveurl";
// _context ... should not be initialize again after it (constructor)
protected Context Context {
get; // in case of C# 6.0+ we can drop the set
}
// _context should be initialized in the derived class constructor
protected DataSeed(Context context) {
if (null == context)
throw new ArgumentNullException("context",
"context should be initialized in the derived class constructor");
// C# 6.0+ feature: assigning to read only property within a costructor
Context = context;
}
// _languages is a list that cannot be changed:
// if you insist on list, IReadOnlyList<string> is a possible choice
// if "cannot be changed" dominates - IReadOnlyCollection<string>
// static: it seems that you don't want to have _languages per each instance
protected static readonly IReadOnlyCollection<String> _languages =
new List<String> { "en", "fr" }.AsReadOnly();
}
编辑:如果是C#5.0-由于Abion47在评论中出现问题,我们可以确保_context
无法分配readonly
但是在构造函数的帮助下{{1 }}
// _context ... should not be initialize again after it (constructor)
private readonly Context _context;
protected Context Context {
get {
return _context;
}
}
// _context should be initialized in the derived class constructor
protected DataSeed(Context context) {
if (null == context)
throw new ArgumentNullException("context",
"context should be initialized in the derived class constructor");
// assigning to read only field within a costructor
_context = context;
}
答案 1 :(得分:1)
注意1:如果您的所有属性和方法的访问范围都低于您的类,则应考虑您的类是否应共享相同的范围。 1}}只要internal
就足够了。
注意2.如果您的实际使用范围相似,我会将DRIVE置于静态类中,并根据以下答案将其他2个属性转换为界面。
1&amp; 3已经由您的数据类型强制执行,但有人可以始终使用new
创建可以更改的其他属性。
2那是由儿童班组成的。您不能从子类中的父类强制构造函数化妆。您只能在父级中创建一个构造函数,子级可以继承该构造函数。
答案 2 :(得分:0)
如果我正确理解您的需要,我可以使用两个字段的私有设置器将它们切换到受保护的属性。
对于常量我只是将其设置为受保护,以便派生类可以访问它。
答案 3 :(得分:0)
您可以使用以下内容,允许子类访问属性,而不允许它们实例化值。
public abstract class DataSeed {
protected Context _context { get; set; }
protected IReadOnlyList<String> _languages { get; private set; } = new List<String> { "en", "fr" }.AsReadOnly();
protected const String DRIVE = "http://mydriveurl";
}
答案 4 :(得分:0)
要将字段公开给派生类,请将它们标记为protected
而不是private
。此外,您可以将_context
标记为readonly
,以便它只能在构造函数中初始化,然后将protected
构造函数添加到派生类调用的DataSeed
。< / p>
此外,如果派生类将其强制转换为_languages
,List
仍然容易受到攻击。相反,您应该考虑使用ReadOnlyCollection
并将其标记为readonly
。
public abstract class DataSeed
{
protected const String DRIVE = "http://mydriveurl";
protected readonly Context _context;
protected readonly ReadOnlyCollection<string> _languages =
(new List<string> { "en", "fr" }).AsReadOnly();
protected DataSeed()
{
_context = someValue;
}
}
public MyDataSeed : DataSeed
{
public MyDataSeed()
: base()
{
// Other constructor-y stuff
}
}