简体   繁体   English

如何将子类作为参数而不是父类传递?

[英]How to pass a child class as a parameter instead of the parent?

I found myself working with a library that defines three clases. 我发现自己正在使用一个定义三个clases的库。 The class Element and the class ElementFile : Element which is a child class of the first one, and a third class called Message . Element和类ElementFile : Element是第一个的子类,第三个类叫Message

I have been copying some functionalities from an other program that has been given to me as an example on how to use the previously mentioned library. 我一直在复制一些其他程序的功能,作为一个例子来说明如何使用前面提到的库。 This program is written in VisualBasic but we are currently working with C# so I ended up finding a part of the code I don't know how to adapt. 这个程序是用VisualBasic编写的,但我们目前正在使用C#,所以我最终找到了一部分我不知道如何适应的代码。

In VisualBasic they are doing this: 在VisualBasic中他们这样做:

Dim message As Message = library.NewMessage
Dim elem As New ElementFile("path")
message.addElement(elem)

And with my lack of knowledge I tried to reproduce it like this in C#: 由于我缺乏知识,我试图在C#中重现它:

Message message = library.NewMessage();
ElementFile elem = new ElementFile("path");
message.addElement(ref elem);

The problem is that the method addElement expects the first parameter to be of Element type. 问题是addElement方法要求第一个参数是Element类型。 I used JustDecompile to check the declaration of this method in the library and it looks like this: 我使用JustDecompile检查库中此方法的声明,它看起来像这样:

public class Message
{
    public void addElement(ref Element elem){ ... }
}

Why is addMethod accepting an ElementFile variable as parameter in VisualBasic and how to do the same in C#? 为什么addMethod接受一个ElementFile变量作为VisualBasic中的参数以及如何在C#中执行相同操作? Can someone confirm me please if the VisualBasic code makes any sense? 如果VisualBasic代码有任何意义,有人可以确认我吗?

Change the declared type of elem to Element , and the C# code will compile: 将声明的elem类型更改为Element ,C#代码将编译:

Element elem = new ElementFile("path");
message.addElement(ref elem);

And here's why : ref Element e means " e must be a thing to which you may assign an instance of Element ". 这里的原因ref Element e的意思是“ e必须是你可以指定实例的事情Element ”。 A reference to ElementFile does not meet that requirement. ElementFile的引用不符合该要求。

The method could be doing this: 该方法可以这样做:

public void Test(ref Element e)
{
    e = new Element();
}

That's fine if the referenced reference back in the caller is of type Element . 如果调用者中引用的引用是Element类型,那Element It's not at all fine if we were given a ref to a reference of a derived type such as ElementFile . 如果我们给出了一个派生类型的引用,例如ElementFile那就没关系了。 Then we'd be effectively doing this: 然后我们会有效地做到这一点:

ElementFile e = new ElementFile();

//  Nope. 
e = new Element();

If we just add a constraint saying the method can't assign to it, then it's not ref any more: You implement exactly that in your method by omitting the ref keyword. 如果我们只是添加一个约束,说方法不能分配给它,那么它就不再ref了:你通过省略ref关键字在你的方法中实现了那个。

So the compiler won't let you do that with ref . 所以编译器不会让你用ref做那件事。

This is essentially the same reason why you can't cast IList<ElementFile> to IList<Element> , but you can cast IEnumerable<ElementFile> to IEnumerable<Element> . 这与您无法将IList<ElementFile>IList<Element>原因相同,但您可以IEnumerable<ElementFile>IEnumerable<Element>

As for the reason why the VB code works, see Hans Passant's excellent answer to a very similar question . 至于VB代码的工作原理, 请参阅Hans Passant对一个非常相似问题的出色答案 VB has an explicit special case for this. VB有一个明确的特例。

It should work if you do this (note the variable type change for elem ): 如果你这样做它应该工作(注意elem的变量类型更改):

Message message = library.NewMessage();
Element elem = new ElementFile("path");
message.addElement(ref elem);

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

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