8

I have a collection class like this:

public class SomeDataCollection : List<ISomeData>
{
    // some method ...
}

but I can't do this:

SomeDataCollection someDatas = new List<ISomeData>();

Cannot implicitly convert type List<ISomeData> to SomeDataCollection. An explicit conversion exists (are you missing a cast?)

so I try to create an implicit coverter inside SomeDataCollection collection class:

public static implicit operator SomeDataCollection(List<ISomeData> l)
{
    var someDatas = new SomeDataCollection();
    someDatas.AddRange(l);
    return someDatas;
}

but it said that I can't create such converter:

SomeDataCollection.implicit operator SomeDataCollection(List<ISomeData>): user-defined conversions to or from a base class are not allowed

And when I cast it like this:

SomeDataCollection someDatas = (SomeDataCollection)new List<ISomeData>();

it throws an error that said:

System.InvalidCastException: Unable to cast object of type List<ISomeData> to type SomeDataCollection.

How can I do this:

SomeDataCollection someDatas = new List<ISomeData>();

without getting an error? Please help. Thanks in advance.

4

4 回答 4

6

A new List<ISomeData>(); is still just a List<ISomeData>. It isn't a SomeDataCollection. The point of subclassing is that the subclass could have extra state etc, but an object (once created) never changes type.

You are not allowed to create operators between types in the same hierarchy, as that would subvert the usual and expected casting behaviour.

You could use simply:

var data = new SomeDataCollection();

However I should add that frankly it is rarely useful to subclass List<T>. Not least, it doesn't expose any useful virtual methods, so you can't tweak the behaviour. I would honestly just use a List<ISomeData> (and remove SomeDataCollection completely) unless I have a clear and demonstrable purpose for it. And then: I might either encapsulate the list, or inherit from Collection<T>.

You could always just add the method as an extension method?

public static class Utils {
    public static void SomeMethod(this IList<ISomeData> list) {
      ...
    }
}

then:

var list = new List<ISomeData>();
...
list.SomeMethod();
于 2012-06-27T07:46:58.327 回答
2

First of all, why do you want to write new List<ISomeData> into a variable defined as SomeDataCollection? It is possible that you actually wanted to SomeDataCollection someDatas = new SomeDataCollection();

As for error messages, the first error message tells you that List<ISomeData> is not derived from SomeDataCollection, therefore you can't do with it something you would do with SomeDataCollection, therefore you can't write it to the variable which is defined as SomeDataCollection (imagine e.g. if SomeDataCollection had public void someMethod() in it, and later in the code you'd call someDatas.someMethod()).

The second error message tells you that converters are intended for converting between completely different types, not between the based and derived type. Otherwise, what would you expect to get e.g. in the following example:

SomeDataCollection a = new SomeDataCollection();
List<ISomeData> b = (List<ISomeData>)a;
SomeDataCollection c = (SomeDataCollection)b;

Should it call your converter or not?

Basically code you're trying to write is very wrong to begin for, so we need to know what're you trying to do, and then maybe well'be able to tell you the solution of your root problem (and not of the problem "how to make this code compile").

于 2012-06-27T07:42:36.147 回答
2

Isn't it better to implement a constructor in SomeDataCollection?

public SomeDataCollection() : base() { }

This could of course be complemented with

public SomeDataCollection(IEnumerable<ISomeData> collection) 
    : base(collection) { }

Then you should be able to initialize your SomeDataCollection like this instead:

SomeDataCollection someData = new SomeDataCollection();
SomeDataCollection someOtherData = 
    new SomeDataCollection(collectionOfSomeData);

and still have access to all the public methods and properties in List<ISomeData>.

于 2012-06-27T07:47:38.547 回答
0

It does not problem with generics. In C# you are not allowed to explicitely convert a base class into a derived class.

于 2012-06-27T07:51:38.487 回答