【问题标题】:VB.NET and calling byval/byref C# overloadsVB.NET 和调用 byval/byref C# 重载
【发布时间】:2018-06-13 11:50:20
【问题描述】:

我们有一个 C# 类,其中包含两个函数,其参数仅通过参数修饰符不同:

bool DoSomething(Object obj){};
bool DoSomething(ref Object obj){};

现在我们需要从 VB.NET 调用这个方法(实际上是其中任何一个)。问题是 VB.NET 编译器无法决定使用哪种方法。

问题是:有没有办法告诉编译器我们想要第一个变体(或第二个变体,这对调用者无关紧要)?

在 VB.NET 中将调用写为 DoSomething((myObj))(即添加括号)没有帮助。

【问题讨论】:

  • IMO 这似乎是一个糟糕的 API 设计。
  • 评论跟踪。所以 C# 认为它是一个不同的函数签名,具有相同的返回类型和相同的参数数量和类型?看起来很奇怪,它不应该那样做......
  • 我能想到的最好方法是 DoSomethingByRef(ref object)
  • 您可能会使用 herehere 描述的方法使用反射(尽管我没有亲自尝试过)调用正确的方法。我仍然会回应其他人在这里所说的话,并考虑更改您的 API 设计以更好地区分方法,特别是因为这对 VB.Net 代码是可见的。
  • 我认为你不能直接这样做。这类似于试图区分名称仅在大小写上有所不同的两种方法。它不是所有语言都支持的功能,因此它被认为是不良形式并且不符合 CLS。例如,see thisthis github issue

标签: c# vb.net byref method-resolution-order byval


【解决方案1】:

AFAIK,唯一的方法是使用反射强制调用 API。虽然我不完全确定这是否可行。

问题在于,创建 2 个仅相差 ref 的重载不符合 CLS,因此不能保证适用于所有 .NET 语言。为防止出现这种情况,您应该将 CLSCompliantAttribute 添加到您的 AssemblyInfo.cs 文件中,然后当您破坏 CLS 兼容性时,编译器会警告您。

[assembly: System.CLSCompliant(true)]

解决此问题的一种方法是添加一个可通过 VB.NET 调用的包装函数。

bool DoSomething(Object obj){};
bool DoSomething(ref Object obj){};

// Call this method from VB.NET
bool DoSomething2(ref Object obj)
{
    return DoSomething(ref obj);
}

有几种不同的方法可以让这个更干净,例如制作一个单独的程序集来包装它,就像 Scott Hannen 提到的那样,或者只是将 CLS 合规性的包装器方法作为扩展方法。

【讨论】:

  • 添加包装函数不会破坏现有 API,只需扩展它即可。
【解决方案2】:

您可以创建一个用 C# 编写的单独库,该库提供具有不同名称的辅助方法,使您能够调用定义不明确的 DoSomething 方法。你不应该这样做,人们可能想知道你为什么这样做,所以你可以用尖刻的 cmets 来填充它,解释为什么它是必要的。

或者你可以使用反射,大致如下:

Dim methods = GetType(WhatEverTheType).GetMethods()
Dim doSomethingMethod = methods.Single(Function(method As MethodInfo)
        Return method.Name = "DoSomething" _
        And Not method.GetParameters()(0).ParameterType.IsByRef
    End Function)
doSomethingMethod.Invoke(instanceOfWhatEverTheType)

【讨论】:

    猜你喜欢
    • 2012-01-21
    • 2020-06-30
    • 2019-04-11
    • 2013-03-16
    • 1970-01-01
    • 2018-03-11
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    相关资源
    最近更新 更多