正确使用C#';新';使受保护的财产公开的修饰符
本文关键字:财产 受保护 | 更新日期: 2023-09-27 18:28:54
假设我有一个抽象基类:
public abstract class BaseClass
{
private MyObject myObject;
protected MyObject PropA
{
get
{
if(myObject == null) this.myObject = new MyObject();
return this.myObject;
}
}
}
并且在我的一个派生的类中,我想使受保护的基类属性PropA
公开。在这种情况下使用new
修饰符是否正确?
public class DerivedClass : BaseClass
{
public new MyObject PropA
{
get
{
return base.PropA;
}
}
}
在这种情况下使用新的修饰符是否正确?
从技术上讲——是的,不会有错误或警告。
对我来说,使用new关键字本身作为修饰符表明了设计上的缺陷。
我举一个例子。
public class MyList<T> : List<T>
{
public int AddCallsCount;
public new void Add(T t)
{
AddCallsCount++;
base.Add(t);
}
}
[TestClass]
public class Test
{
[TestMethod]
public void TestThatsNotGood()
{
List<object> list = new MyList<object>();
list.Add(1);
list.Add(2);
MyList<object> myList = list as MyList<object>;
Assert.AreEqual(0, myList.AddCallsCount);
}
}
多态性看起来是有效的,但实际上并没有。
更新:好的,有一个非常简单的解释。我省略了多态性的解释
利用abstract'virtual
和overriding
方法实现了多态性。只要没有指定virtual
和override
修饰符,MyList<T>.Add
就只是另一个"通用"公共方法。由于MyList<T>
继承了List<T>
,MyList<T>.Add
"隐藏"了List<T>.Add
,因为两种方法的名称和参数相同。
在较低级别:只要方法Add
的List<T>
类型定义没有用virtual
关键字标记,编译器就不会为给定类型的变量(在这种情况下为List<T>
)搜索实际实例类型(在这种特定情况下为MyList<T>
)的重写方法。
当然,它可能会导致逻辑错误和类API的不正确使用。
因此,编译器"认为"可能存在逻辑错误或设计缺陷,并警告程序员。new
关键字只是与编译器对话的一种方式
是的,我知道它不好,但我需要它,因为我的设计不好
如果要在派生类中添加与基类中成员同名的成员,则new
关键字有效且正确;然而,这种设计似乎违背了抽象类的目的。使PropA
在基类中公开和虚拟或公开和抽象:
public abstract class BaseClass
{
// Property not implemented here.
public abstract MyObject PropA { get; }
private MyObject _propB;
// Property implemented, but implementation can be overridden in derived class.
public virtual MyObject PropB
{
get { return _propB ?? (_propB = new MyObject()); }
}
public int PropC { get { return 5; } }
}
public class DerivedClass : BaseClass
{
// You must provide an implementation here.
private MyObject _propA;
public override MyObject PropA
{
get { return _propA ?? (_propA = new MyObject()); }
}
// You are free to override this property and to provide an new implementation
// or to do nothing here and to keep the original implementation.
public override MyObject PropB
{
get { return <new implementation...>; }
}
// PropC is inherited as is and is publicly visible through DerivedClass as well.
}
我建议你也许是
public new string test {
get { return (this as T).test; }
set { (this as T).test = value; }
}
因为base
只给你父母,但如果你想走得更高,你必须投。