简体   繁体   English

c#从基类隐式转换

[英]c# implicit conversion from base class

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 . 无法将类型List<ISomeData> 隐式转换为SomeDataCollection An explicit conversion exists (are you missing a cast?) 存在显式转换(您是否错过了演员?)

so I try to create an implicit coverter inside SomeDataCollection collection class: 所以我尝试在SomeDataCollection集合类中创建一个隐式转换器:

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 SomeDataCollection.implicit operator SomeDataCollection(List<ISomeData>)不允许在基类之间进行用户定义的转换

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 . System.InvalidCastException:无法转换List<ISomeData>类型的对象以键入SomeDataCollection

How can I do this: 我怎样才能做到这一点:

SomeDataCollection someDatas = new List<ISomeData>();

without getting an error? 没有收到错误? Please help. 请帮忙。 Thanks in advance. 提前致谢。

A new List<ISomeData>(); 一个new List<ISomeData>(); is still just a List<ISomeData> . 仍然只是一个List<ISomeData> It isn't a SomeDataCollection . 它不是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> . 但是我应该坦率地补充一下,对List<T>进行子类化很少有用。 Not least, it doesn't expose any useful virtual methods, so you can't tweak the behaviour. 尤其是,它不会暴露任何有用的virtual方法,因此您无法调整行为。 I would honestly just use a List<ISomeData> (and remove SomeDataCollection completely) unless I have a clear and demonstrable purpose for it. 老实说,我只是使用List<ISomeData> (并完全删除SomeDataCollection ),除非我有明确和可证明的目的。 And then: I might either encapsulate the list, or inherit from Collection<T> . 然后:我可以封装列表,也可以从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();

First of all, why do you want to write new List<ISomeData> into a variable defined as SomeDataCollection ? 首先,为什么要将new List<ISomeData>写入定义为SomeDataCollection的变量? It is possible that you actually wanted to SomeDataCollection someDatas = new SomeDataCollection(); 你有可能真的想要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 eg if SomeDataCollection had public void someMethod() in it, and later in the code you'd call someDatas.someMethod() ). 对于错误消息,第一条错误消息告诉您List<ISomeData>不是从SomeDataCollection派生的,因此您无法使用SomeDataCollection执行SomeDataCollection ,因此您无法将其写入已定义的变量作为SomeDataCollection (想象一下,如果SomeDataCollection在其中有public void someMethod() ,稍后在代码中你将调用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 eg 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"). 基本上你要编写的代码是非常错误的,所以我们需要知道你想要做什么,然后很可能能够告诉你你的根问题的解决方案(而不是问题的解决方案) “如何编译此代码”)。

Isn't it better to implement a constructor in SomeDataCollection ? 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

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

and still have access to all the public methods and properties in List<ISomeData> . 并且仍然可以访问List<ISomeData>所有公共方法和属性。

It does not problem with generics. 它与泛型没有问题。 In C# you are not allowed to explicitely convert a base class into a derived class. 在C#中,不允许将基类明确地转换为派生类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM