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

时间:2017-12-12 16:47:05

标签: c#

我发现自己正在使用一个定义三个clases的库。类Element和类ElementFile : Element是第一个的子类,第三个类是Message

我一直在复制其他程序中的一些功能,作为如何使用前面提到的库的示例。这个程序是用VisualBasic编写的,但我们目前正在使用C#,所以我最终找到了一部分我不知道如何适应的代码。

在VisualBasic中,他们这样做:

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

由于我缺乏知识,我试图在C#中重现它:

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

问题是方法addElement期望第一个参数是Element类型。 我使用JustDecompile检查库中此方法的声明,它看起来像这样:

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

为什么addMethod在VisualBasic中接受ElementFile变量作为参数以及如何在C#中执行相同操作?如果VisualBasic代码有意义,有人可以确认一下吗?

2 个答案:

答案 0 :(得分:3)

将声明的Element类型更改为Element elem = new ElementFile("path"); message.addElement(ref elem); ,C#代码将编译:

ref Element e

Multi-project Builds - Gradlee表示“Element必须是 ,您可以指定ElementFile”的实例。对public void Test(ref Element e) { e = new Element(); } 的引用不符合该要求。

方法可以这样做:

Element

如果调用者中引用的引用属于ElementFile类型,那就没问题。 如果我们被赋予对ElementFile e = new ElementFile(); // Nope. e = new Element(); 等派生类型的引用的引用,那就没有问题。然后我们会有效地做到这一点:

ref

如果我们只是添加一个约束,说该方法无法分配给它,那么它就不再是ref:您可以通过省略ref关键字在方法中实现该方法。

因此,编译器不允许您使用IList<ElementFile>执行此操作。

这与你无法将IList<Element>投射到IEnumerable<ElementFile>的原因基本相同,但可以IEnumerable<Element>投射到bp = new BillingProcessor(this, LICENSE_KEY, MERCHANT_ID, new BillingProcessor.IBillingHandler() { @Override public void onProductPurchased(@NonNull String productId, @Nullable TransactionDetails details) { showToast("onProductPurchased: " + productId); updateTextViews(); } @Override public void onBillingError(int errorCode, @Nullable Throwable error) { showToast("onBillingError: " + Integer.toString(errorCode)); } @Override public void onBillingInitialized() { showToast("onBillingInitialized"); readyToPurchase = true; updateTextViews(); } @Override public void onPurchaseHistoryRestored() { showToast("onPurchaseHistoryRestored"); for(String sku : bp.listOwnedProducts()) Log.d(LOG_TAG, "Owned Managed Product: " + sku); for(String sku : bp.listOwnedSubscriptions()) Log.d(LOG_TAG, "Owned Subscription: " + sku); updateTextViews(); } });

关于VB代码工作的原因,And here's why。 VB有一个明确的特例。

答案 1 :(得分:0)

如果你这样做(注意elem的变量类型更改):

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