2014-11-01 36 views
1

比方说,我有一个抽象基类正确使用C#“新”改性剂,使受保护的财产公开

public abstract class BaseClass 
{ 
    private MyObject myObject; 

    protected MyObject PropA 
    { 
     get 
     { 
      if(myObject == null) this.myObject = new MyObject(); 
      return this.myObject; 
     } 
    } 
} 

...这在我的派生类之一,我想使保护基类属性PropA公众。在这种情况下使用new modifier是否正确?

public class DerivedClass : BaseClass 
{ 
    public new MyObject PropA 
    { 
     get 
     { 
      return base.PropA; 
     } 
    } 
} 
+3

这并非非常错误。为什么你不能在基类中公开它是很难猜测的。也许只有一个BaseClass引用的客户端程序员会陷入麻烦。 – 2014-11-01 22:24:14

+0

那么,它的技术上是正确的,但乍一看,它似乎是一个可疑的设计。为什么'PropA'保护如果它可以在某些派生类中公开?为什么不开始公开?是什么让公共'PropA'成为其他派生类中糟糕的设计? – InBetween 2014-11-01 23:01:19

回答

0

这是正确的。任何时候,如果您有一个成员与继承类中的成员具有相同名称的类,则需要使用new关键字(即使这两个属性/方法具有不同的返回类型)。

3

在这种情况下使用新修饰符是否正确?

技术上 - 是的,不会有错误或警告。

至于我,使用新的关键字本身作为修饰符表示设计缺陷。

我举一个例子。

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\virtualoverriding方法实现多态性。只要没有指定virtualoverride修饰符MyList<T>.Add只是另一种“常见”公共方法。并与MyList<T>继承List<T>,MyList<T>.Add'隐藏'List<T>.Add,因为两个方法的名称和参数是相同的。

在较低的水平:一旦方法AddList<T>类型定义没有标记virtual关键字,编译器将不搜索重写实际实例类型的方法(MyList<T>在这种情况下,某些),用于给定类型的变量(在这种情况下为List<T>)。

定义它可能导致类API的逻辑错误和不正确的使用。

因此,编译器'认为'可能存在逻辑错误或设计缺陷并警告程序员。该new关键字只是一个交谈的编译器

方式是的,我知道这是不好的,但我需要它,因为我的糟糕设计

+0

这将有助于解释为什么(和哪里)多态性(令人惊讶地)失败。另外,从'List '继承'可以说[*不是一个好主意](http://stackoverflow.com/a/5376343/1497596)。 – DavidRR 2014-11-01 23:31:39

+0

@DavidRR,您可以将列表更改为SomeBaseClass和MyList 以SomeDerivedClass。没关系。列表示例很自然,这是我第一次想到。 – 2014-11-01 23:43:25

2

如果您想在与基类中的成员具有相同名称的派生类中添加成员,那么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. 
}