2010-03-23 50 views
1

根據this question它似乎可以做到這一點的方法。我想知道的是爲什麼當我嘗試使用屬性時它不起作用。從C#4.0 RC1爲什麼我不能同時覆蓋和新建一個Property(C#)?

錯誤1型 'ClassLibrary1.Foo' 已經

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; } 
    } 
} 

錯誤消息包含關於 '值' ClassLibrary1的\定義的Class1.cs 31 22 ClassLibrary1的

回答

4

您不能有兩個屬性使用相同的名稱。這在C#中是不允許的。唯一的例外是索引器,因爲對於索引器,簽名會根據索引類型進行更改。

對於只有返回類型不同的方法,您不能重載。具有單一名稱的屬性基本上被相同的規則禁止,因爲它在內部是一對沒有get訪問器參數的方法。

+0

+1我不知道我怎麼可以肯定,但這似乎是正確的答案 - 同樣的規則不打方法,因爲方法重載等。 – 2010-03-24 01:30:17

+0

@Tim:在這裏閱讀最後一段:http://msdn.microsoft.com/en-us/library/aa691131(v=VS.71).aspx相同的規則適用於屬性 – 2010-03-24 05:56:58

0

你有兩個相同的屬性Value的定義,其中一個由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 
+0

是的,這完全是我想要的行爲。我想要的有趣的是:((Foo)foo_)。值//調用Foo上的實現 2010-03-24 01:23:34

+0

嚴格地說,覆蓋不需要名稱。它只需要一些關聯到正確的v表插槽的方法。不幸的是,C#只使用名稱(C++/CLI,我相信MSIL也有明確的關聯方式)進行關聯。 – 2010-03-24 23:19:52

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 
+0

我不得不想出一個稍微不同的解決方法,因爲我的基類不是抽象的,它實際上應該與對象一起工作(當它使用類型參數構造它時,它只會停止與對象一起工作)。 – 2010-03-24 01:20:12

1

你可以用interace得到這個。

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; 
    } 
} 
1

潛在的問題是,它永遠無法知道使用哪個屬性。

例如,

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

s.Value = "hmmm"; 

所以應該使用哪個屬性? int從對象派生,也符合通用屬性版本的約束。

+0

我的意圖是,這將拋出(如果你可以讓它編譯:-)) – 2010-03-24 01:29:02

+1

它不會含糊不清。重寫的虛擬屬性將用於通過基類引用進行多態訪問,新屬性將用於通過與派生類(或其任何後代)進行靜態類型化的引用進行訪問。一種方法是使用中間基類來提供重載定義。 – 2010-03-24 23:18:09

2

即使C#不能,C++/CLI也可以做到。在C++/CLI中,您可以明確指出哪個方法被覆蓋,所以名稱不必匹配。

+0

+1有趣! – 2010-03-24 01:25:19

+0

+1非常有趣。 – 2011-05-08 12:52:36

相關問題