2013-01-01 53 views
2

你能幫我理解在這種情況下的錯誤嗎?簡單的通用誤解

public interface IGeneralInterface 
{ 
} 


public class A : IGeneralInterface 
{ 
} 

public class B : IGeneralInterface 
{ 
} 

public class SomeClass<TGenericType> where TGenericType : IGeneralInterface 
{ 
    private TGenericType internalValue; 

    public SomeClass(TGenericType InitValue) 
    { 
     internalValue = InitValue; 
    } 

    public TGenericType CreateAnother() 
    { 
     TGenericType val1 = new B(); //Error here: class B() could not be converted to TGenericType 
     return val1; 
    } 
} 

即使我建立SomeClass<T>作爲

SomeClass<IGeneralInterface> someClass = new SomeClass<IGeneralInterface>(); 

我明確地傳遞基本接口包括所有(?)的情況下,它仍然拋出一個錯誤

回答

3

變化

TGenericType val1 = new B(); //Error here: class B() could not be converted to TGenericType 

IGeneralInterface val1 = new B(); 

您正在嘗試TypeCast IGeneralInterfaceTGenericType這是導致錯誤的原因。

TGenericType可能有其他限制,例如它繼承ISpecificInterface,其中B donot繼承。在這種情況下,分配變得無效。

實施例:

public class SomeClass< TGenericType> where TGenericType : IGeneralInterface, ISpecificInterface 
TGenericType val1 = new B(); // TGenericType should be ISpecificInterface also, B is not. 

對於上面運行。 IGenericInterface應該總是比TGenericType更具體。

public class SomeClass <IGenericInterface> 

另外,您可以使用關鍵字is找出對象是否是分配給TGenericType然後用鑄件。

TGenericType val1 = default(TGenericType); 
var val = new B(); 
if (val is TGenericType) 
{ 
    val1 = (TGenericType)val; 
} 

編輯對於下面的評論

它如何能在運行時有額外的要求嗎?一切我把編譯器這裏列出

CreateAnother()創建B類型是不通用的實例。 以下面的例子

SomeClass<C> c = new SomeClass<C(); 
C another = c.CreateAnother(); // C is not assignable from B. (C is below). But It would be valid, if compiler did not flag the error 

public class C : IGeneralInterface, IDisposable 
{ 
} 
+0

您正在嘗試將TypeCast IGeneralInterface引入TGenericType,這是導致錯誤的原因。 < - 是的。爲什麼會發生?我明確發送IGeneralInterface作爲TGenericType的類型 – Jasper

+1

但是'TGenericType'也可以擴展其他接口,其中'IGenericInterface'沒有 – Tilak

+0

@Jasper:不,你沒有。你只需要TGenericType實現IGeneralInterface。由於在運行時使用的TGenericType可能有其他要求,因此您的類無法知道如何將'B'轉換爲TGenericType可以調用的任何類型。 – RBarryYoung

0

在你的代碼的問題是,你是在聲明變量

val1 
類型的

TGenericType 

,然後嘗試通過一個對象實例化它不同的類型。

即使您聲明瞭您的類的泛型類型必須位於IGeneralInterface的繼承層次結構中,它們對於編譯器而言也是不同的。我假設在這個設置中你將不得不使用明確的演員。

1

爲什麼你認爲new B()應該兌換成TGenericType?唯一知道的關於TGenericType的是它實現了接口。

作爲示例,new B()無法轉換爲A類型。

我不知道你想獲得什麼,而是你可以在通用的限制更改爲:

public class SomeClass<TGenericType> 
    where TGenericType : class, IGeneralInterface, new() 

然後,它會確定地說new TGenericType()你創建方法內。

但將不再能夠使用類型SomeClass<IGeneralInterface>因爲接口不具有可訪問的參數實例構造函數(無接口可以有構造函數,當然)。

+0

作爲一個例子,新的B()不能轉換爲類型A. < - 它可以通過它們都從中繼承的接口。或者至少他們可以轉換爲基礎接口。而基礎接口**它是**類型的泛型類(TGenericType) – Jasper

+1

@Jasper這聽起來像是你把事情弄錯了。所謂的傳遞性意味着如果X轉換爲Y,Y轉換爲Z,則X轉換爲Z.但是不能反轉方向。你有:**'TGenericType'轉換爲'IGeneralInterface' **和**'B'轉換爲'IGeneralInterface' **。但是這兩次轉換都是** ** IGeneralInterface'。所以你不能使用傳遞性來推斷任何關於'B'和'TGenericType'是可互換的。 –

+0

謝謝!這是我錯過的部分。謝謝 ! (對不起 - 我已經給了Tilak的'回答',因爲他/她是第一個) – Jasper