首页 > 解决方案 > Why can't generic extension method be called with explicit generic arguments?

问题描述

I have the following extension method:

Module MyModule

    <Extension()>
    Public Function MyExtension(Of T)(value As T, i As T) As Short
        Return Nothing 'omitted'
    End Function

End Module

I can call it in a variety of ways:

Dim fake As IFoo
fake.Bar().MyExtension(1)
MyModule.MyExtension(Of Integer)(fake.Bar(), 1)

But it seems to impossible to call it as an extension method with an explicit generic type parameter:

fake.Bar().MyExtension(Of Integer)(1)

Is there a way to do that in VB? I can do it easily in C# with this syntax:

IFoo fake = null;
fake.Bar().MyExtension<int>(1);

标签: .netvb.netgenericsextension-methods

解决方案


来自扩展方法(C# 编程指南)(强调添加):

扩展方法使您能够将方法“添加”到现有类型,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但它们被称为扩展类型上的实例方法。对于用 C#、F# 和 Visual Basic 编写的客户端代码,调用扩展方法和在类型中实际定义的方法之间没有明显区别。

C# 和 VB 的区别在于上面高亮文本的解释。

对于具有这些签名的 C# 扩展方法:

public static short MyExtension<T>(this T value, T i)
{
    return default(short);
}

public static short MyExtension2<T1, T2>(this T1 value, T2 i)
{
    return default(short);
}

作为扩展方法的相应用途看起来像(忽略可以推断的类型):

SomeType v0 = null;
SomeType v1 = null;
v1.MyExtension<SomeType>(v0);
v1.MyExtension2<SomeType, int>(2);

C# 只允许调用静态方法,就好像它们是实例方法一样,而不考虑“好像它们是扩展类型上的实例方法”部分。VB 采用了一种更深入的转换方法,使签名看起来好像真的是一个实例方法。

相应的实例方法签名看起来像这样:

internal class SomeType
{
    public short MyExtensionInstance(SomeType i)
    {
        return default(short);
    }

    public short MyExtension2Instance<T2>(T2 i)
    {
        return default(short);
    }

}

调用实例方法如下所示:

SomeType v0 = new SomeType();
SomeType v1 = new SomeType();
v1.MyExtensionInstance(v0);
v1.MyExtension2Instance<int>(2);

这正是 VB 对扩展方法强制执行的语法,因为它们被调用就好像它们是扩展类型上的实例方法一样

现在回答你的问题;在这种基本的实现差异方面,没有办法强迫 VB 像 C# 一样行事。

实际上,我无法理解您为什么更喜欢 C# 风格。指定扩展类型是冗长且多余的。我发现它还引入了与扩展方法的不一致,其中this参数不是通用的,通过在不需要也没有好处的地方引入鸡蛋-鸡-鸡蛋(类型-方法-类型)模式。


推荐阅读