2012-03-27 15 views
1

クラスの派生クラスIntersectionPathのコンストラクタ内のオブジェクトのリストを次のようにキャストしようとしています。ジェネリックリストの明示的キャストが機能しないのはなぜですか

public class IntersectionPath : Path<IntersectionSegment>, IEnumerable 
    {   

     //Constructors 
     public IntersectionPath() : base() { Verts = null; } 

     public IntersectionPath(List<Intersection> inVerts, List<Segment<Node>> inEdges) : base() 
     { 
      this.Segments = (List<IntersectionSegment>) inEdges; 
     } 

    } 

セグメントが

public class Path<T> : IEnumerable<T> where T : Segment<Node> 
    { 
     //public properties 
     public List<Direction> Directions {get; set; } 
     public List<T> Segments { get; set; } 
    } 

汎用の基本クラスパスに定義されている私は(下記参照してなぜこれがしようとしないよう不明確だIntersectionSegmentクラス内のキャストの明示的な演算子を定義しています。私はIntersectionPathコンストラクタ内の鋳造のためのエラーメッセージを持ってコンパイル

public class IntersectionSegment : Segment<Intersection> 
{   
    //curves which intersect the primary curve at I0(Start Node) and I1(End Node) 
    public Curve C0 { get; set; } 
    public Curve C1 { get; set; } 

    public IntersectionSegment():base() {} 

    public IntersectionSegment(Intersection n0, Intersection n1):base(n0,n1){} 

    public static explicit operator IntersectionSegment(Segment<Node> s) 
    { 
     if ((s.Start is Intersection) && (s.End is Intersection)) 
     { 
      return new IntersectionSegment(s.Start as Intersection,s.End as Intersection); 
     } 
     else return null; 
    } 

    public static explicit operator List<IntersectionSegment>(List<Segment<Node>> ls) 
    { 
     List<IntersectionSegment> lsout = new List<IntersectionSegment>(); 
     foreach (Segment<Node> s in ls) 
     { 
      if ((s.Start is Intersection) && (s.End is Intersection)) 
      { 
       lsout.Add(new IntersectionSegment(s.Start as Intersection,s.End as Intersection)); 
      } 
      else return null; 
     } 
     return lsout; 
    } 

セグメントは次のように定義されます。

public class Segment <T> : Shape where T : Node 
{ 
    //generic properties 
    public T Start { get; set; } 
    public T End { get; set; } 

} 
+1

あなたは*たくさんのコードを提供しています - それを1つの短い完全なプログラムに減らすことはできますか? –

+0

私はそれを実現します....私はちょうど前の投稿で見つかった私はより多くのコードを求められる! :-s – gwizardry

+1

*完全な*コードを与えていないのであれば、一般的にもっと尋ねられるでしょうが、短いものと完全なものは通常大丈夫です。 –

答えて

7

List<InteractionSegment>は、InteractionSegmentと同じではありません。 1つのタイプのリストを別のタイプのリストにキャストしても、各アイテムはキャストされません。
あなたはこのような何かをする必要があります。

this.Segments = inEdges.Select(x => (InteractionSegment)x).ToList(); 

これはInteractionSegmentオブジェクトへinEdges内の各オブジェクトをキャストするオブジェクトへのLINQを使用して、this.Segmentsに割り当てられたリストに戻って結果を置きます。

+0

よろしくお願いいたします。私が明示したキャストのポイントは、これを克服することだと思ったので、私は推論を理解しているかどうかはわかりません。 – gwizardry

+0

'InteractionSegment'と' Segment 'と' List 'と' List > 'の間に**ない**の間に明示的なキャストを書いています。あなたの明示的なキャストは、私のコードでは依然として必要であり、使用されています –

+0

私は両方とも書いていると思った。 – gwizardry

2

List<Segment<Node>>List<IntersectionSegment>ではないため、単純に機能しません。後でを作成したい場合は、あなたが明示的にしたいタイプにリスト内の各項目をキャストするCast()を使用することができます。

this.Segments = inEdges.Cast<IntersectionSegment>().ToList(); 
4

はのは、はるかに少ない混乱の例を見てみましょう。

class Animal {} 
class Giraffe : Animal {} 
class Tiger : Animal {} 
... 
List<Giraffe> giraffes = new List<Giraffe>(); 
List<Animal> animals = (List<Animal>) giraffes; // illegal 

「最後の行のキャストはなぜ違法ですか?」と私は信じています。

それは合法だとしましょう。今度は別の行を追加します:

animals.Add(new Tiger()); 

動物リストには虎を追加できますか?しかし、その動物リストは、実際にはキリンのリストです。キャストはコピーリストではなく、 "私はこのタイプのものとしてこのオブジェクトを扱いたい"と言います。しかし、そうすることで、あなたはキリンのリストに虎を置くような狂気のことをすることができますので、私たちはキャストを違法にします。

あなたの状況は、同じ状況のはるかに複雑なバージョンです。

この質問は、ほぼ毎日StackOverflowで尋ねられます。 「共分散と反共分散」を探し、数十の例を見つけます。

+0

私は動物が、上の行で新しくされたキリンと同じオブジェクトにアクセスする変数ラベルであることを見ています。すなわちそのちょうど参考となる。そうであれば、正規の明示的キャストで作成された新しいオブジェクトはどうなりますか(List の代わりにAnimalを作成したとします)? – gwizardry

+0

@gwizardry: 'Animal'から' List 'にユーザー定義の明示的変換演算子を作成したい場合は、それでいいです。そのような変換は 'Animal'から' List 'に変換されるので、' Giraffe'を 'List 'に変換することができます。しかし結果は 'List 'ではありません。 –

+0

いいえ、私は動物にキリンを意味しませんでした。しかし、もし私が新しいオブジェクトを返すなら、私の質問はロジックに関するものでした(私は上記のキャスト演算子でやっています)。これは、このオブジェクトをこのタイプのものとして扱うという記述を変更しますか? – gwizardry

関連する問題