开发者

Casting an object to a base collection

I'm not totally convinced this is possible, but here goes. I have a method returning an object, although the actual type is Collection. Now, I can easily cast the object into the collection using

var myCollection = myObject as Collection<MyClassA>;

However the problem I have is that Collection<MyClassA> could alternatively be Collection<MyClassB> or Collection<MyClassC>. All of these MyClassX's are inherited from MyBaseClass, so ideally I would like to be able to do something like

var myCollection = myObject as Collection<MyBaseClass>;

However this throws an exception when casting. Is it possible to do this in anyway? I understand that it may be within .Net 4?

Thanks for the help.

EDIT: OK - The answers so far 开发者_StackOverflow社区are very useful, however they only solve the second part of the solution - converting/casting collections.

I am still unsure as to how I should initially cast the object to a collection (without the use of a huge if statement for each of the possible types)


This is only supported with IEnumerable<T> in .NET 4. Check out the difference in the signatures:

IEnumerable<T>:

public interface IEnumerable<out T> : IEnumerable

Collection<T>:

public class Collection<T> : IList<T>, 
ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable

That out keyword in the type parameter is what tells .NET to support variance.


Before I had access to .NET 4 I wrote an extension method that achieved this:

public static IEnumerable<U> CastCollection<T, U>(this IList<T> items) where U : class
{
   var collection = new List<U>();
   foreach (var item in items)
   {
      if (item is U)
      {
           var newItem = item as U;
           collection.Add(newItem);
      }
  }
  return collection;
}

You would use it like this:

var myCollection = myObject.CastCollection<MyClassA, MyBaseClass>();

myCollection will be an IEnumerable<MyBaseClass> in this case.


Alternate solution: you could use interfaces and generics to get what you want.

public interface IMyClass
{
}

public class MyClassA : IMyClass
{
}

public class MyClassB : IMyClass
{
}

public class MyClassC : IMyClass
{
}

static void Main(string[] args)
{
    var listA = new List<IMyClass>{new MyClassA{}, new MyClassA{}};
    var listB = new List<IMyClass> { new MyClassB { }, new MyClassB { } };
    var listC = new List<IMyClass> { new MyClassC { }, new MyClassC { } };

    List<IMyClass> genericList = listA.Cast<IMyClass>().ToList();
}

Something like this will compile properly and also allow you to assign different lists of any types that implement the common interface, to the same variable (in this case genericList.


This cannot be done by casting the collection as a whole. However, you can cast the individual elements to a new collection. Look at LINQ's Cast<> extension method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜