2012-04-18 30 views
-1

我已經發布this question with a bad sample如何在c#中實現泛型多態 - 第2部分?

此代碼應該更好。

爲了避免混淆,我總結了一些代碼:

using System.Collections.Generic; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main() 
     { 
      IManager<ISpecificEntity> specificManager = new SpecificEntityManager(); 
      IManager<IAntoherSpecificEntity> anotherSpecificManager = new AnotherSpecificEntityManager(); 
      Dictionary<string, IManager<IIdentifier>> managers = new Dictionary<string, IManager<IIdentifier>>(); 
      managers.Add("SpecificManager", (IManager<IIdentifier>)specificManager); 
      managers.Add("AnotherSpecificManager", (IManager<IIdentifier>)anotherSpecificManager); 

      foreach (var manager in managers.Values) 
      { 
       IIdentifier entity = manager.Container.GetEntity(); 
      } 
     } 
    } 

    internal interface IIdentifier 
    { 
     int Id { get; set; } 
    } 

    internal interface ISpecificEntity : IIdentifier 
    { 
     string SpecificValue { get; set; } 
    } 

    internal class SpecificEntity : ISpecificEntity 
    { 
     public int Id { get; set; } 
     public string SpecificValue { get; set; } 
    } 


    internal interface IAntoherSpecificEntity : IIdentifier 
    { 
     string AnotherSpecificValue { get; set; } 
    } 

    internal class AntoherSpecificEntity : IAntoherSpecificEntity 
    { 
     public int Id { get; set; } 
     public string AnotherSpecificValue { get; set; } 
    } 

    internal interface IContainer<out TIdentifier> where TIdentifier : IIdentifier 
    { 
     TIdentifier GetEntity(); 
    } 

    internal interface ISpecificContainer : IContainer<ISpecificEntity> 
    { 
    } 

    internal class SpecificContainer : ISpecificContainer 
    { 
     public ISpecificEntity GetEntity() 
     { 
      return new SpecificEntity { SpecificValue = "SpecificValue" }; 
     } 
    } 

    internal interface IAnotherSpecificContainer : IContainer<IAntoherSpecificEntity> 
    { 
    } 

    internal class AnotherSpecificContainer : IAnotherSpecificContainer 
    { 
     public IAntoherSpecificEntity GetEntity() 
     { 
      return new AntoherSpecificEntity { AnotherSpecificValue = "AnotherSpecificValue" }; 
     } 
    } 

    internal interface IManager<TIdentifier> where TIdentifier : IIdentifier 
    { 
     IContainer<TIdentifier> Container { get; set; } 
    } 

    internal class SpecificEntityManager : IManager<ISpecificEntity> 
    { 
     public IContainer<ISpecificEntity> Container { get; set; } 
    } 

    internal class AnotherSpecificEntityManager : IManager<IAntoherSpecificEntity> 
    { 
     public IContainer<IAntoherSpecificEntity> Container { get; set; } 
    } 
} 

當我調試的代碼我在第12行

得到一個InvalidCastException在Main()我知道ISpecificEntity實現IIdentifier。 但是顯然直接從IManager<ISpecificEntity>轉換成IManager<IIdentifier>不起作用。

我認爲使用協方差可以做到這一點,但將IManager<TIdentifier>更改爲IManager<in TIdentifier>IManager<out TIdentifier>也不起作用。

那麼,有沒有辦法將specificManager轉換成IManager<IIdentifier>

謝謝,一切順利。

+1

應該告訴你哪些主要的線()是有問題的。你能告訴我們嗎? – 2012-04-18 15:50:12

+0

可能的重複[如何在c#中實現泛型多態?](http://stackoverflow.com/questions/10211072/how-to-implement-generic-polymorphism-in-c) – 2012-04-18 15:54:40

+0

不要重新發布,編輯和改進你的問題。 – 2012-04-18 15:56:15

回答

1

首先你會明白泛型的錯誤。

如果你看Foo它是一個泛型類型。 Foo和Foo是NEW類型,它們不是從List派生的,也沒有通過繼承來連接類型。 使用泛型創建新類型,它不會派生!

但是你要找的是Covariance and Contravariance。這將允許您創建一種「通用多態性」,但您需要在您的通用定義中指定此類型。因此,它僅適用於開箱即用的極少數框架泛型。

class Program 
{ 
    static void Main(string[] args) 
    { 
     IManager<IIdentifier> f1 = new C1(); 
     IManager<IIdentifier> f2 = new SpecificEntityManager(); //IManager<ISpecificEntity> 
    } 
} 

interface IIdentifier { } 
interface ISpecificEntity : IIdentifier { } 
interface IManager<out T> { } 

class C1 : IManager<IIdentifier> { } 
class SpecificEntityManager : IManager<ISpecificEntity> { } 

這裏是你必須改變:

internal interface IContainer<out TIdentifier> where TIdentifier : IIdentifier 
{ 
    TIdentifier GetEntity(); 
} 
internal interface IManager<out TIdentifier> where TIdentifier : IIdentifier 
{ 
    IContainer<IIdentifier> Container { get; } 
} 
internal class SpecificEntityManager : IManager<ISpecificEntity> 
{ 
    public IContainer<IIdentifier> Container { get; set; } 
} 
internal class AnotherSpecificEntityManager : IManager<IAntoherSpecificEntity> 
{ 
    public IContainer<IIdentifier> Container { get; set; } 
} 
+0

你完全誤解了這個問題。 – SLaks 2012-04-18 16:11:20

+0

實際上,我知道了,它正常工作,如果你使用正確的語法。添加了一個代碼示例。 – Jaster 2012-04-18 16:19:07

+0

完美!這在示例代碼中起作用。我希望我可以在生產中使用它! ;-)謝謝,一切順利! – Palama 2012-04-19 06:26:07

0

難道你不需要一個非泛型IManager IManager <TIdentifier>可以繼承。然後IManager <IIdentifer>是一個IManager,可以被鑄造?

+0

如果將有IManager將繼承的通用「ISuperManager」,我如何訪問通用屬性Container? – Palama 2012-04-18 15:59:55

+0

不一定。 IManager 可以從一個不通用的空IManager繼承。 IManager 的IManagers ...我想。 – 2012-04-18 16:02:44