2013-02-06 47 views
3

我試圖製作一個模板類的列表,將基類傳遞給模板。但似乎這是不允許的。有沒有辦法繞過這個限制,或者更適當地重構我的代碼?模板的一般錯誤

下面是一個抽象的例子:

using System; 
using System.Collections.Generic; 

namespace TempInherit 
{ 
    abstract class Shape{} 

    class Triangle : Shape{} 
    class Square : Shape{} 

    class ShapeHolder<T>{} 

    class MainClass 
    { 
     public static void Main(string[] args) 
     { 
      // list of base class, add subclass - works 
      List<Shape> shapes = new List<Shape>(); 
      shapes.Add(new Triangle()); 
      shapes.Add(new Square()); 

      // list of holders of base class, add holders of subclass - fails 
      List<ShapeHolder<Shape>> shapeHolders = new List<ShapeHolder<Shape>>(); 
      shapeHolders.Add(new ShapeHolder<Triangle>()); 
      shapeHolders.Add(new ShapeHolder<Square>()); 
     } 
    } 
} 

其中產量:

錯誤CS1502:用於 `System.Collections.Generic.List>。新增(TempInherit最好重載方法匹配。 ShapeHolder)' 有一些無效參數(CS1502)(TempInherit)

Error CS1503:Argument #1' cannot convert TempInherit.ShapeHolder'expre裂變鍵入 `TempInherit.ShapeHolder」(CS1503)(TempInherit)

+0

你能否提供更多關於ShapeHolder的代碼和Shape? –

+0

@DmitryMartovoi:我已經添加了我的完整代碼,但它只是一個模擬我在真實應用程序中出現的錯誤的小示例。我敢肯定,這是我對C#泛型的誤解,因爲我是一個使用Xamarin的iOS/Android開發人員。 – Josh

+0

原因是ShapeHolder 不被視爲從ShapeHolder繼承

回答

6

協方差問題:

您可以創建一個接口IShapeHolder<out T>,作爲接口的通用參數可以是協變的(但不是類)

類似的東西

public class Shape 
    { 
    } 
    public class Triangle : Shape 
    { 
    } 
    public class Square : Shape 
    { 
    } 
    //T generic parameter is covariant (out keyword) 
    public interface IShapeHolder<out T> where T : Shape 
    { 
    } 
    public class ShapeHolder<T> : IShapeHolder<T> where T: Shape 
    { 
    } 

然後,

var shapes = new List<Shape>(); 
shapes.Add(new Triangle()); 
shapes.Add(new Square()); 

// list of holders of base class, add holders of subclass - fails no more 
var shapeHolders = new List<IShapeHolder<Shape>>(); 
shapeHolders.Add(new ShapeHolder<Triangle>()); 
shapeHolders.Add(new ShapeHolder<Square>()); 
+2

提問者注意,這不允許從'shapeHolder'中檢索項目。但是這是設計意圖,否則你可以通過將'SquareHolder '投射到'ShapeHolder '來將'Square'插入到'ShapeHolder '中。 – Dykam

+0

好像是一個標記界面,沒有使用它 –

+0

這樣做的工作非常好,謝謝! – Josh