为什么我不能同时覆盖和新建一个Property(C#)?

时间:2010-03-23 23:01:55

标签: c# .net inheritance methods

根据 this question ,您似乎可以为方法执行此操作。我想知道的是为什么当我尝试使用属性时它不起作用。

public class Foo
{
    public virtual object Value
    {
        get;
        set;
    }
}

public class Foo<T> : Foo
{
    public override object Value
    {
        get
        {
            return base.Value;
        }
        set
        {
            base.Value = (T)value; //inject type-checking on sets
        }
    }

    public new T Value
    {
        get { return (T)base.Value; }
        set { base.Value = value; }
    }
}

来自C#4.0 RC1的错误消息

  

错误1类型   'ClassLibrary1.Foo'已经   包含'Value'的定义   ClassLibrary1 \ Class1.cs 31 22   ClassLibrary1的

6 个答案:

答案 0 :(得分:4)

您不能使用相同名称的两个属性。这在C#中是不允许的。唯一的例外是索引器,因为在索引器的情况下,签名会按索引类型更改。

对于仅因返回类型而异的方法,不能重载。具有单个名称的属性基本上被同一规则禁止,因为它在内部是一对没有get访问器参数的方法。

答案 1 :(得分:3)

如果您执行以下操作,则可以执行此操作...

public interface IFoo<T>
{
    T Value { get; set; }
}

public class Foo<T> : Foo, IFoo<T>
{
    T IFoo.Value
    {
        get { return (T)base.Value; }
        set { base.Value = value; }
    }
}

唯一的问题是,当你引用时,你必须使用接口类型......即

   IFoo<int> myfoo = new Foo<int>();
   int result = myFoo.Value;    //This will give you the typed version

   Foo<int> myfoo = new Foo<int>();
   int result = myFoo.Value;    //This will give throw an exception

答案 2 :(得分:2)

即使C#不能,也可以使用C ++ / CLI。在C ++ / CLI中,您可以明确说明正在覆盖哪个方法,因此名称不必匹配。

答案 3 :(得分:1)

您可以通过界面获得此功能。

public interface IFoo
{
    object Value { get; set; }
}

public class Foo<T> : IFoo
{
    object _value = null;
    object IFoo.Value
    {
        get { return _value; }
        set { _value = value; }
    }

    public T Value
    {
        get;
        set;
    }
}

答案 4 :(得分:1)

潜在的问题是永远不知道要使用哪个属性。

例如,

Foo<int> s = new Foo<int>();

s.Value = "hmmm";

那么应该使用哪个属性? int派生自object,也符合通用属性版本的约束。

答案 5 :(得分:0)

您有两个相同属性Value的定义,一个由override定义,另一个由new定义。返回类型不是方法签名中的区别特征,即如果签名仅在返回类型中不同,则签名被认为是相同的。所以,使用override或new。

在你的情况下,你可以使用new而不是override来实现目标。但是,在使用new时,您始终必须考虑执行的执行情况取决于您调用方法的类型。即。

var foo = new Foo();
var foo_ = new Foo<string>();

foo.Value            // calls the implementation on Foo 
foo_.Value           // calls the implementation on Foo<T>
((Foo) foo).Value    // calls the implementation on Foo