2016-08-03 198 views
1

我有以下類:`Activator.CreateInstance`和派生類型`new`屬性

public class HeaderBase 
{ 
    public int HeaderSize { get { return sizeof(byte); } } 
    public byte[] Content { get; private set; } 

    public HeaderBase(byte[] bytes) 
    { 
     Content = bytes; 
    } 
} 

public class BiggerHeader : HeaderBase 
{ 
    public new int HeaderSize { get { return sizeof(byte) + sizeof(UInt32); } } 

    public BiggerHeader(HeaderBase header) : base(header.Content) 
    { }  
} 

我也有一個模板的方法來編組和實例化BiggerHeader類型

public static T Get<T>() where T : HeaderBase 
{ 
    HeaderBase b = new HeaderBase(new byte[]{}); 
    T instance = (T)Activator.CreateInstance(typeof(T), b); 
    return instance; 
} 

根據到MSDN

where T : <base class name>:type參數必須是或者是從指定的基類派生

但是,HeaderSize的值是1而不是5,正如我所預料的那樣。爲什麼會出現這種情況,我如何實例化一個將使用派生類型的new屬性的對象?

DotNetFiddle

相關:Generics in C# - how can I create an instance of a variable type with an argument?

+1

刪除'new'關鍵字,C#編譯器現在可以生成一個警告。你需要了解那個警告,現在你不需要。在這個網站上有很多關於它的好Q + A。使用'new'來抑制警告是一個錯誤。 –

+0

@HansPassant我明白這一點。我需要基類來執行基於'HeaderSize'的邏輯,而不是繼承的大小。我的問題是'Activator'創建的實例的行爲像基類而不是派生類型,儘管這是我通過作爲參數傳遞給'CreateInstance'的參數類型 – user5877732

+0

它與創建的實例無關激活器,一切與你的參考變量的類型有關。哪一個是HeaderBase,任何非虛擬成員都將採取非虛擬行爲。 –

回答

3

new成員具有相同的名稱作爲基本部件,但不相關。看起來你想在派生類中使用virtualoverride

隨着new你基本上沉默了告誡你這個警告。 new沒有功能影響。

T上的呼叫解析好像THeaderBase。其他任何情況都會要求運行時根據您調用的名稱在運行時執行動態綁定。想象一下T t; t.Xyz();。該代碼無法編譯,因爲沒有發現靜態的Xyz。但你正在做同樣的事情!在編譯該方法時,沒有可見的Derived.HeaderSize,因爲我們不知道T將會是Derived。它可能最終成爲別的東西。這就是爲什麼呼叫靜態綁定到Base.HSB.HSD.HS具有相同的名稱的事實意味着什麼。這是巧合。

+0

我明白'new'和'override'是什麼意思。問題是爲什麼對'Activator.CreateInstance'的調用似乎創建了一個'BaseHeader'的實例,而不是派生類,它是傳遞給函數的參數 – user5877732

+0

它創建一個派生實例,但變量的類型爲T是有效的HeaderBase類型。所以,如果你說instance.HeaderSize你調用的基本方法。這就好像你說的((Base)實例).HeaderSize。這清楚地說明了基本方法。 – usr

+0

*變量的類型爲T,它是有效類型的HeaderBase *,但是**爲什麼**是這種情況?我將我想要的類型傳遞給'CreateInstance';我想在哪裏得到關於基類的任何事情?該方法約束特別說,它允許派生類型...我錯過了什麼? – user5877732

1

嗯,我相信主要錯誤是由於糟糕的體系結構。

讓我們添加一些改進,並使所有屬性必須在每個其他派生類中更改 - abstract。通過這樣做,我們將確保我們不會忘記任何東西,並且可以開始使用多態(覆蓋行爲)。

我們也使用C#6.0

一些功能它也會讓代碼更易讀:

public abstract class AbstractHeader 
{ 
    public abstract int HeaderSize { get; } 
    public virtual byte[] Content { get; set; } 

    protected AbstractHeader() { } 

    protected AbstractHeader(byte[] bytes) 
    { 
     Content = bytes; 
    } 
} 

public class BaseHeader : AbstractHeader 
{ 
    public override int HeaderSize => sizeof (byte); 
} 

public class BiggerHeader : AbstractHeader 
{ 
    public override int HeaderSize => sizeof (byte) + sizeof (UInt32); 

    public BiggerHeader(BaseHeader header) : base(header.Content) 
    { 
    } 
}