2011-07-10 12 views
1

我有一個基類ScenBase和派生類ScenC。我有一個從基類Hex中派生的類HexC。我也有一個來自基類Unit的類UnitC。我可以設置十六進制的數組指向HexC數組,但是編譯器不會讓我設置單位的名單指向UnitC列表:C#:的<T>列表=列表<源自T>不編譯

// The Core Database for the game scenario. 
// Theoretically multiple secenarios can be loaded 
// into memory at the same time. 
[Serializable] 
public class ScenC : ScenBase 
{ 
    public bool playable { get; set; } 
    public HexC[,] hexCs { get; private set; } 
    public List<UnitC> unitCs { get; private set; } 

    // A database for every user and AI entity. 
    public List<ScenV> chViews { get; private set; } 
    public List<string> characters { get; private set; } 

    public ScenC(int xDimI, int yDimI) : base (xDimI, yDimI) 
    { 
     playable = false; 
     chViews = new List<ScenV>(); 
     characters = new List<string>(); 
     characters.Add("Supreme"); 
     hexCs = new HexC[xDim, yDim]; 
     hexs = hexCs;    //this line complies fine 
     newHex = (int x, int y) => new HexC(this, x, y); 
     unitCs = new List<UnitC>(); 

     // **This line won't compile** 
     unitCs = units; 
     Init(); 
    } 
} 

下面是該領域的性質基類ScenBase:

[Serializable] 
public abstract class ScenBase 
{ 
    public Hex[,] hexs; 
    public List<Unit> units { get; protected set; } 
    public DateTime currGameTime { get; set; } 
    public int xDim { get; set; } 
    public int yDim { get; set; } 
    public double scale { get; protected set; } 
    protected delegate Hex NewHex(int x, int y); 
    protected NewHex newHex; 

    //Rest of Class not shown for simplicity 
} 

爲什麼我不能設置一個List<Hex>List<HexC>後面的「是」隱式轉換規則時,但我可以設置爲陣列

+0

C#不支持類的協變性。而在集合上它也不是類型安全的。 – CodesInChaos

回答

4

array這是不可能的。

如果可行,您可以將其他派生類型添加到列表中。
例如:

List<Car> cars = new List<Car> 
List<Vehicle> vehicles = cars; //Error! 
vehicles.Add(new Bicycle());  //That's not a car! 

什麼你問的是所謂協方差;這只是可能不變接口(如IEnumerable<T>

+0

啊我明白了。它的後續添加元素使其輸入不安全。我想可以將T的數組設置爲指向從T派生的數組,因爲數組元素通常會聲明一次,而不會在稍後添加。我正在考慮讓ScenBase類成爲通用的,但我很高興我問了這個問題,因爲現在我可以看到語言規則背後的推理。 –

+0

@Rich:你的猜測是錯誤的。數組協方差是不安全的,只允許出於傳統原因。因爲它們是協變的,所以數組需要在運行時檢查類型兼容性。 – SLaks

+0

那麼通常最好是最小化數組的使用並使用泛型集合呢?我可以爲二維十六進制數組創建一個自定義泛型集合並創建我自己的迭代器,以便它可以像2維數組一樣訪問 –

0

不可能像SLaks說,你可以用一個接口來代替。 IList<IHex>例如...

1

你可以使用的接口列表(1),其中十六進制和單位符合以某種方式被提名的接口。否則,您需要投射。

REF:http://msdn.microsoft.com/en-us/library/dd465120.aspx

順便說一句:IEnumerable的任何一個接口是協變已經(見:http://msdn.microsoft.com/en-us/library/9eekhta0.aspx)。語法:out in IEnumerable < out T>定義了協方差。

(1)的A接口的列表

using System; 
using System.Collections.Generic; 

public interface IHex { 
    string ToString(); 
} 

public class Hex : IHex 
{ 
    public override string ToString() { return "Hex"; } 
} 

public interface IHexC : IHex {} 
public class HexC : Hex 
{ 
    public override string ToString() { return "HexC"; } 
} 

public class Test{ 
    public static void Main() 
    { 
     IList<IHex> HexList = new List<IHex>(); 

     HexList.Add(new Hex()); 
     HexList.Add(new HexC()); 
     HexList.Add(new HexC()); 

     foreach(var o in HexList){ 
      Console.WriteLine(o.ToString()); 
     } 

    } 
} 

控制檯輸出:

六角

HexC

HexC


+0

您不能將顯式或隱式類型轉換爲List。 –

+0

爲你提供了一個更好的例子。名單得到解決。 – sgtz

0

你不能施放

List<UnitC> // UnitC - to a derived from a Unit class 

List<Unit> // Unit - the base class 

嘗試用IUNIT接口而不是

+0

這沒有幫助。 – SLaks

0

一般的角度來考慮,除了SLaks'解釋至於爲什麼你的代碼不工作是使用泛型定義了一個新類型:

Unit is a type. 
UnitC is a type derived from Unit. 

List<Unit> is a new type. 
List<UnitC> is a new type, but is not derived from List<Unit>. 

然而,

Hex[] defines multiple instances of the Hex type. 
HexC[] defines multiple instances of the HexC type (which is derived from Hex). 

你的任務不工作,因爲編譯器不能確保單位的元素實際上是UnitC的情況,但如果你試圖逆(單位= unitCs)那也行不通,因爲List < UnitC>不是從列表<單元派生的。