2017-10-15 84 views
1

說我有,其存儲泛型參數輸入值的通用接口:多個類

public interface IFoo<TValue> 
{ 
    TValue SomeValue { get; set; } 
} 

然後,我有兩個班,StringFooDoubleFooSomeValuesstring S和double小號分別爲:

public class StringFoo : IFoo<string> 
{ 
    string SomeValue { get; set; } 
} 

public class DoubleFoo : IFoo<double> 
{ 
    double SomeValue { get; set; } 
} 

我現在決定,我想,可以同時包含StringFoo S和數組個S:

var foos = IFoo<object>[] { 
    new StringFoo { SomeValue = "a value" }, 
    new DoubleFoo { SomeValue = 123456789 } 
} 

我倒是覺得,因爲這兩個stringdoubleobject子類,他們都希望能在這個數組中允許的。但是,我認爲是錯誤的。

所以,我嘗試使用協方差:

public interface IFoo<out TValue> 

,但由於接口同時包含getter和setter方法,我不能這樣做。

那麼,可以在一個數組中實現通用接口的兩個類

+3

的可能的複製[C# - 在一個列表中的多個泛型類型(https://stackoverflow.com/questions/353126/c-sharp-multiple-generic-types-in-one-list) – Fruchtzwerg

+0

列表和T []是完全不同的結構,顯然可以從一個轉換到另一個,但可能會根據未來的語言設計顯示非常不同的行爲決策及其基礎運行時實現。這就是爲什麼這個問題完全不同。事實上,從語言理論的角度來看,今天的答案相似或相同並不重要。 –

回答

1

該問題可以通過Bar類實現的方式來解決(也提供了壞例子)。問題是,無論何時試圖使用通用接口或類實現通用接口代碼可能會編譯(提供正確的強制轉換),但代碼將在運行時引發InvalidCastException。

public interface IFoo<TValue> 
{ 
    TValue SomeValue { get; set; } 
} 

public class StringFoo : IFoo<string> 
{ 
    public string SomeValue { get; set; } 
} 

public class DoubleFoo : IFoo<double> 
{ 
    public double SomeValue { get; set; } 
} 

public class Foo<TValue> : IFoo<TValue> 
{ 
    public TValue SomeValue { get; set; } 
} 

public abstract class Bar 
{ 

} 

public class Bar<TValue> : Bar, IFoo<TValue> 
{ 
    public TValue SomeValue { get; set; } 
} 

public static class Verify 
{ 
    public static void QuestionArray() 
    { 
     var foos = new IFoo<object>[] 
     { 
      (IFoo<object>) new StringFoo { SomeValue = "a value" }, 
      (IFoo<object>) new DoubleFoo { SomeValue = 123456789 } 
     }; 
    } 

    public static void BadAnswerArray() 
    { 
     var foo = new IFoo<object>[] 
     { 
      (IFoo<object>) new Foo<string>(), 
      new Foo<object>(), 
     }; 
    } 

    public static void GoodAnswer() 
    { 
     var foo = new Bar[] 
     { 
      new Bar<string>(), 
      new Bar<object>(), 
      new Bar<double>() 
     }; 
    } 
} 

,並驗證解決方案可以運行測試,其中只有GoodAnswerTest將通過:

public class GenericsInArrayTests 
{ 
    [Fact] 
    public void QuestionArrayTest() 
    { 
     Verify.QuestionArray(); 
    } 

    [Fact] 
    public void BadAnswerTest() 
    { 
     Verify.BadAnswerArray(); 
    } 

    [Fact] 
    public void GoodAnswerTest() 
    { 
     Verify.GoodAnswer(); 
    } 
} 
+0

如果沒有抽象類的使用,那麼我們在這裏實際上可能不需要。 –

+0

@jacek有沒有可能沒有投到'IFoo '?沒有它的代碼看起來會更乾淨(並且寫得更短)。 – Zoweb

+0

@jacek此外,當我嘗試使用投射,VS告訴我「可疑的演員:沒有類型的解決方案,這是繼承自StringFoo和IFoo 」 *編輯*而我剛剛意識到'酒吧'是爲非鑄造...正確... – Zoweb