为什么 resharper 更喜欢不将抽象类的属性隐藏在另一个抽象类中

本文关键字:抽象类 隐藏 另一个 属性 更喜欢 为什么 resharper | 更新日期: 2023-09-27 18:37:27

为什么re-sharper希望我不隐藏抽象类的属性?它希望我使用"新",但这总是更可取的吗?这似乎暗示隐藏一个变量,让用户不能做base.property是一件坏事。

我只是对这个OO概念有点困惑,想知道是否有强有力的理由支持或反对它。

我有

public abstract class baseClass{
 protected string commonProperty {get; set;}
}
public abstract class moreSpecificBaseClass : baseClass {
   // Resharper would prefer I use 'new' below
   protected string commonProperty = "Some specific setting"; 
}
public class verySpecificClass : moreSpecificBaseClass {
// Some code
}

为什么 resharper 更喜欢不将抽象类的属性隐藏在另一个抽象类中

来自 MSDN 文档:

尽管可以在不使用 new 修饰符的情况下隐藏成员,但 结果为警告。如果使用 new 显式隐藏成员,则 禁止显示此警告并记录派生的事实 版本旨在作为替换。

隐藏类成员可能会导致误解和细微的错误。因此,编译器会警告您,并要求您通过使用"new"修饰符明确隐藏可能有害的成员的意图。这可以防止意外隐藏基类型成员被忽视。

请参阅以下小示例,了解隐藏成员时问题如何潜入代码:

    public abstract class A
    {
        public int Value = 0;
    }
    public class B : A
    {
        // This hides the Value member from the base type A
        public new int Value = 0;
    }
    static void SetValue(B obj, int value)
    {
        obj.Value = value;
    }
    static void AddToValue(A obj, int value)
    {
        obj.Value += value;
    }
    static void Main(string[] args)
    {
        B obj = new B();
        SetValue(obj, 11);
        AddToValue(obj, 5);
        Console.Out.WriteLine("obj.Value = " + obj.Value);
        Console.Out.WriteLine("((A) obj).Value = " + ((A) obj).Value);
        Console.Out.WriteLine("((B) obj).Value = " + ((B) obj).Value);
    }

这将输出:

obj.Value = 11
((A) obj).Value = 5
((B) obj).Value = 11

仅通过查看 Main 方法的流程,您可能会认为在方法的末尾是 obj 的值。值为 16 (=11+5)。但事实并非如此 - 更糟糕的是:根据您访问 Value 成员的方式,您会遇到不同的值。

现在,在这个小示例中,输出不相同且并非在所有情况下都达到预期值的原因可能很容易且快速地发现。但是想象一下,具有许多类,大量继承,抽象基类或接口类型的方法参数,第三方类库,您命名的更大的软件项目,并且隐藏成员引起的问题可能会变得更加难以识别。

如果你不希望外界能够访问base.property,它应该受到保护。 如果是,则不应在派生类中重新定义它。 如果它根本不可用于派生类,请将其设为私有。

它建议新的防止歧义,但实际上你不应该一开始就在那里。

原因是如果我这样做:

var item = new verySpecificClass();
var val = item.commonProperty;
var basic = (baseClass)item;
if(val == basic.commonProperty)

我将得到与一个理性的程序员所期望的不同的结果。