2011-07-10 7 views
1

私はベースのクラスScenBaseと派生クラスScenCを持っています。私はクラスHexCを基底クラスのHexから導出しました。私は基本クラスUnitから派生したクラスUnitCも持っています。私はHexCの配列を指すように六角の配列を設定することができますが、コンパイラは私がUnitCのリストを指すようにユニットのリストを設定できません。ここでC#:<T>のリスト= of <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:それは暗黙のキャストルール「である」が、私はこれが不可能である配列

+0

C#ではクラスの共分散はサポートされていません。コレクションでは型保証もされていません。 – CodesInChaos

答えて

4

に配列を設定することができ、次のときに私はList<HexC>List<Hex>を設定することはできませんなぜ

[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<Car> cars = new List<Car> 
List<Vehicle> vehicles = cars; //Error! 
vehicles.Add(new Bicycle());  //That's not a car! 

何が共分散と呼ばれるために求めています。 (例えばIEnumerable<T>のような)不変のインターフェースの場合にのみ可能です。

+0

ああ、私は参照してください。後でその要素を追加すると、安全でない型になります。私は、Tの配列を、Tから派生した配列を指すように設定するのはOKだと思います。なぜなら、配列要素は通常は一度宣言され、後では追加されないからです。とにかくScenBaseクラスを汎用的にすることを考えていましたが、言語ルールの背後にある推論を見ることができるので、私は質問してうれしいです。 –

+0

@リッチ:あなたの推測は間違っています。配列の共分散は安全ではなく、従来の理由でのみ許可されています。それらは共変であるため、配列は実行時に型の互換性をチェックする必要があります。 – SLaks

+0

配列の使用を最小限に抑え、ジェネリックコレクションを代わりに使用するのが一般に良いですか?私は、2次元の16進数の配列のカスタムジェネリックコレクションを作成し、2次元配列のようにアクセスできるように私自身のイテレータを作成することができます –

0

代わりに、インターフェースを使うことができます。 IList<IHex>たとえば...

1

ここでは、16進数と単位が何らかの方法で指定されたインターフェイスに準拠しているインターフェイスのリストを使用できます(1)。それ以外の場合は、キャストする必要があります。

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

がところで:IEnumerableを任意のインターフェースが既に(:http://msdn.microsoft.com/en-us/library/9eekhta0.aspx参照)共変です。構文:(IEnumerable)< out T>は共分散を定義します。

(1)インターフェースのリスト

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

リストに明示的または暗黙的な型変換を行うことはできません。 –

+0

があなたのためのより良い例を考え出しました。リストはそれを回避します。 – sgtz

0

あなたはSLaks'説明に加えて、代わりに

+0

それは役に立たないでしょう。 – SLaks

0

IUnitインターフェースを検討するための一般的なポイントにしてみてください

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

List<Unit> // Unit - the base class 

にキャストすることはできませんコードが機能しない理由は、ジェネリックを使用すると新しいタイプが定義されるということです。

あなたの割り当ては動作しません
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>はリスト<ユニット>から派生していないため、どちらもうまくいきません。

関連する問題