2009-08-12 6 views
24

List<Obj>とキャストできないのはなぜですか?なぜ次は動作しません:C#リストをキャストする<ObjBase>をリストとして<Obj>

internal class ObjBase 
    { 
    } 

internal class Obj : ObjBase 
    { 
    } 

internal class ObjManager 
{ 
    internal List<Obj> returnStuff() 
    { 
     return getSomeStuff() as List<Obj>; 
    } 

    private List<ObjBase> getSomeStuff() 
    { 
     return new List<ObjBase>(); 
    } 

} 

は、代わりに私はこれをしなければならない。

internal class ObjBase 
    { 
    } 

internal class Obj : ObjBase 
    { 
    } 

internal class ObjManager 
{ 
    internal List<Obj> returnStuff() 
    { 
     List<ObjBase> returnedList = getSomeStuff(); 
     List<Obj> listToReturn = new List<Obj>(returnedList.Count); 
     foreach (ObjBase currentBaseObject in returnedList) 
     { 
      listToReturn.Add(currentBaseObject as Obj); 
     } 
     return listToReturn; 
    } 

    private List<ObjBase> getSomeStuff() 
    { 
     return new List<ObjBase>(); 
    } 
} 

私は(読みやすくするために短縮)2008のVisual Studioで、次のエラーが表示されます。

ができません参照変換、ボクシング変換、アンボクシング変換、ラッピング変換、またはヌル型変換を介して 'List'から 'List'に変換する

ありがとうございます。

+0

-1:http://stackoverflow.com/questions/1263489/how-など、ここでは多くの質問、のDUP 1263514#1263514と答えに引用されているもの –

+0

[.NET Casting Generic List](http://stackoverflow.com)の重複している可能性があります。/questions/674715/net-casting-generic-list) –

答えて

1

あなたがしようとしているキャストを誤解していると思います。実際にリスト自体のタイプを変更しようとしているリストに格納されているオブジェクトのタイプを変更していると考えています。あなたがすでにそれを入力したときにリスト自体を変更することはできないということはむしろ意味があります。

あなたはそれを基本クラスのリストとして見て、リスト項目を処理しているときにそれをキャストすると、これが私のアプローチになります。

この試行されたキャストの目的は何ですか?

0

LINQのはConvertAll方法があります。なので

list.ConvertAll<Obj>(objBase => objbase.ConvertTo(obj)); 

私は他に何を提案するか分かりません。私は、ObjBaseが基本クラスであると仮定し、すべてのObjBaseオブジェクトがObjオブジェクトである場合、なぜ最初の2つのオブジェクトを持つのかはわかりません。おそらく私はマークから外れています。

編集:list.Castメソッドは、互いにキャスト可能であると仮定すると、上記よりもうまく機能します。私は他の答えを読むまでそれを忘れてしまった。

9

で 見て、私は唯一のJavaビューから「問題」を記述することができますが、どのような少しから私はこの観点は、両方のC#とJavaで同じことを知っている:

List<ObjBase>List<Obj>ではない、ので、 ObjオブジェクトではないObjBaseオブジェクトを含むことができます。かつての保証は、後者は受け付けませんObjBase引数でAdd()コールを受け入れるようにするので

List<Obj>周りの他の方法はList<ObjBase>にキャストできないことができます!

だから要約する: Objがあるにもかかわらず、 ObjBase List<Obj>List<ObjBase> ではありません。

+0

これは私が読んだ一般的な共変量問題の最も単純な記述です。ニース。 –

1

現在、C#はジェネリック型の差異をサポートしていません。私が読んだことから、これは4.0で変更されます。

ジェネリックスの差異の詳細については、hereを参照してください。

32

System.LinqのCastToList拡張メソッドを使用して、これを1行に含めることができます。

代わり

internal List<Obj> returnStuff() 
{ 
    return getSomeStuff() as List<Obj>; 
} 

の次の操作を行います。

internal List<Obj> returnStuff() 
{ 
    return getSomeStuff().Cast<Obj>().ToList(); 
} 
0

これは、C#での主要な痛みである - これはジェネリックが設計された方法です。 ListはListを拡張しません。まったく別の型です。あなたはキャストすることはできませんまたはどのような方法でお互いに割り当てる、唯一のオプションは、他の1つのリストをコピーすることです。

0

Lazarusは:
私は、コンパイラは、私は、リストのオブジェクトに対して行われたアクションを望んでいない私はリスト自体をキャストしようとしていたということを理解するであろうと思いました。

いくつかの詳細情報:このDLLの外

public abstract class ObjBase 
    { 
    } 

internal interface IDatabaseObject 
    { 
    } 

public class Obj : ObjBase, IDatabaseObject 
    { 
    } 


internal interface IDatabaseObjectManager 
    { 
     List<ObjBase> getSomeStuff(); 
    } 

public class ObjManager : IObjManager 
{ 
    public List<Obj> returnStuff() 
    { 
     return getSomeStuff().Cast <Customer>().ToList<Customer>(); 
    } 

    private List<ObjBase> getSomeStuff() 
    { 
     return new List<ObjBase>(); 
    } 
} 

クライアントコードは行くことができます: ObjManager objM =新しいObjManager(); リストlistOB = objM.returnStuff(); 私はアプリケーションのこの部分(O/RM)に複数のObjObjManagerを作成します。ここで

(ダーンコメントブロックは、文字を使い果たした!:-)

1

list.ConvertAllは魅力的ですが、大きな欠点が1つあります。新しいリストが作成されます。これは、特に大きなリストのパフォーマンスとメモリ使用量に影響を与えます。

もう少し手間をかけて、元のリストを内部参照として保持し、使用時にのみアイテムを変換するラッパーリストクラスを作成できます。

使用法:あなたのライブラリに追加する

var x = new List<ObjBase>(); 
var y = x.CastList<ObjBase, Obj>(); // y is now an IList<Obj> 

コード:

public static class Extensions 
{ 
    public static IList<TTo> CastList<TFrom, TTo>(this IList<TFrom> list) 
    { 
     return new CastedList<TTo, TFrom>(list); 
    } 
} 

public class CastedList<TTo, TFrom> : IList<TTo> 
{ 
    public IList<TFrom> BaseList; 

    public CastedList(IList<TFrom> baseList) 
    { 
     BaseList = baseList; 
    } 

    // IEnumerable 
    IEnumerator IEnumerable.GetEnumerator() { return BaseList.GetEnumerator(); } 

    // IEnumerable<> 
    public IEnumerator<TTo> GetEnumerator() { return new CastedEnumerator<TTo, TFrom>(BaseList.GetEnumerator()); } 

    // ICollection 
    public int Count { get { return BaseList.Count; } } 
    public bool IsReadOnly { get { return BaseList.IsReadOnly; } } 
    public void Add(TTo item) { BaseList.Add((TFrom)(object)item); } 
    public void Clear() { BaseList.Clear(); } 
    public bool Contains(TTo item) { return BaseList.Contains((TFrom)(object)item); } 
    public void CopyTo(TTo[] array, int arrayIndex) { BaseList.CopyTo((TFrom[])(object)array, arrayIndex); } 
    public bool Remove(TTo item) { return BaseList.Remove((TFrom)(object)item); } 

    // IList 
    public TTo this[int index] 
    { 
     get { return (TTo)(object)BaseList[index]; } 
     set { BaseList[index] = (TFrom)(object)value; } 
    } 

    public int IndexOf(TTo item) { return BaseList.IndexOf((TFrom)(object)item); } 
    public void Insert(int index, TTo item) { BaseList.Insert(index, (TFrom)(object)item); } 
    public void RemoveAt(int index) { BaseList.RemoveAt(index); } 
} 

public class CastedEnumerator<TTo, TFrom> : IEnumerator<TTo> 
{ 
    public IEnumerator<TFrom> BaseEnumerator; 

    public CastedEnumerator(IEnumerator<TFrom> baseEnumerator) 
    { 
     BaseEnumerator = baseEnumerator; 
    } 

    // IDisposable 
    public void Dispose() { BaseEnumerator.Dispose(); } 

    // IEnumerator 
    object IEnumerator.Current { get { return BaseEnumerator.Current; } } 
    public bool MoveNext() { return BaseEnumerator.MoveNext(); } 
    public void Reset() { BaseEnumerator.Reset(); } 

    // IEnumerator<> 
    public TTo Current { get { return (TTo)(object)BaseEnumerator.Current; } } 
} 
関連する問題