您有一個錯誤在您的C#代碼。
要覆蓋C#函數,您必須指定override
關鍵字。 如果您再次編寫virtual
您正在使用基本功能,但沒有new
關鍵字,您應該會收到警告。
如果兩者都聲明爲虛擬的,則有兩個具有相同名稱的函數!
讓我們做一個例子...
public class Base
{
public Base() { fun(); }
public virtual void fun() { Console.Write(1); }
}
public class Derived : Base
{
public Derived() { fun(); }
public override void fun() { Console.Write(2); }
}
public class DerivedWithError : Base
{
public DerivedWithError() { fun(); }
public new virtual void fun() { Console.Write(3); }
}
...
// This will print "22".
Base normal = new Derived();
Console.WriteLine();
// This will print "13" !!!
Base withError = new DerivedWithError();
Console.WriteLine();
// Let's call the methods and see what happens!
// This will print "2"
normal.fun();
Console.WriteLine();
// This will print "1" !!!
withError.fun();
Console.WriteLine();
陰影是指「具有相同的名稱添加一個新的方法,而無需使用polymorfism」。 沒有override
關鍵字,您正在禁用polymorfism。
因此,一切都應該乾淨,現在很容易理解。
DerivedWithError.fun()是一種全新的虛擬方法。它在基類中具有與fun函數相同的名稱,但它們不相關!
從虛擬表(或虛擬方法表,如果您更喜歡另一個名稱)的角度來看,使用映射基函數和派生函數佔用虛表中的兩個不同條目,並且如果它們具有相同的名稱。 如果使用override
來代替,則強制派生類中的func方法覆蓋由Base.func佔用的虛擬表項,這是多態性。
危險但被.NET允許,總要小心語法!
您可以在C#中的構造函數中調用虛函數,但通常在派生類中,如果在基構造函數中調用方法,則應該小心如何使用派生類中的字段。 現在,爲了保持清潔並避免混淆和風險,您應該避免在構造函數中調用虛擬方法,但實際上它幾次都非常有用。
例如所謂的「工廠方法」,它不能訪問任何變量。
public abstract class MyClass
{
public IList<string> MyList { get; private set; }
public MyClass()
{
this.MyList = this.CreateMyList();
}
protected abstract IList<string> CreateMyList();
}
public class MyDerived : MyClass
{
protected override IList<string> CreateMyList()
{
return new ObservableCollection<string>();
}
}
這是完全合法的,它的工作原理!
您能提供一個鏈接到描述不同行爲的材料嗎? –
我不是C#人員,但我相信我在實際的C#2.0標準中讀過關於這個主題的筆記。我會稍後再挖掘它。你正在使用哪種C#版本? –
確實存在C#代碼錯誤,正如答案中所述。 –