C# 基于扩展方法的模板专门化

C# 基于扩展方法的模板专门化,c#,C#,在C#中,我希望泛型类的一个方法以不同的方式运行,使用类似于 我从C#中看到,使用扩展可能会出现这样的情况,但我的代码没有按预期运行:我希望thing::Method()有一个行为,而不是时有另一个行为 我有 using System; public interface IThing { void Method(); } public class Thing<T> : IThing { public void Method() { thi

在C#中,我希望泛型类的一个方法以不同的方式运行,使用类似于

我从C#中看到,使用扩展可能会出现这样的情况,但我的代码没有按预期运行:我希望
thing::Method()
有一个行为,而
不是
时有另一个行为

我有

using System;

public interface IThing
{
    void Method();
}

public class Thing<T> : IThing
{
    public void Method() 
    {
        this.Specialization<T>();
    }
}

public static class ThingExtensions
{
    public static void Specialization<T>(this Thing<T> cls)
    {
        Console.WriteLine("Thing<T> specialization");
        return;
    }

    public static void Specialization(this Thing<int> cls)
    {
        Console.WriteLine("Thing<int> specialization");
        return;
    }
}

public class Program
{
    public static void Main()
    {
        var t = new Thing<float>();
        t.Method();
        t.Specialization();

        var i = new Thing<int>();
        i.Method();
        i.Specialization();
    }
}
使用系统;
公共接口
{
void方法();
}
公共类的东西:我喜欢
{
公开作废法()
{
这个。专门化();
}
}
公共静态类ThingExtensions
{
公共静态无效专门化(这个东西是cls)
{
Console.WriteLine(“事物专业化”);
返回;
}
公共静态无效专门化(这个东西是cls)
{
Console.WriteLine(“事物专业化”);
返回;
}
}
公共课程
{
公共静态void Main()
{
var t=新事物();
t、 方法();
t、 专门化();
var i=新事物();
i、 方法();
i、 专门化();
}
}
但这是一种输出

Thing<T> specialization
Thing<T> specialization
Thing<T> specialization
Thing<int> specialization
事物专门化
事物专门化
事物专门化
事物专门化
而不是

Thing<T> specialization
Thing<T> specialization
Thing<int> specialization
Thing<int> specialization
事物专门化
事物专门化
事物专门化
事物专门化
“为什么不直接调用
专门化
而不是
方法
?”这一显而易见的问题有望通过我的接口类的加入得到回答——我正在尝试适应它的框架


我可以看出
专业化
专业化
是匹配的,但我很惊讶后者没有被视为更好的匹配

不幸的是,当您调用
Method()
时,它作为
Thing
运行,而不知道它是
Thing
。您可以使用反射来发现这一点,或者(更好的主意):

if(Thing x的这个实例)
x、 专业化();
其他的
这就是专业化;

或者,您可以将
Method()
声明为
virtual
并使用
override void Method(){…}
调用
this.Specialization()在编译包含的方法时解析。在这一点上,
T
是任何东西

<>一些通用支持语言(如C++)在所有类型参数(或C++的情况下,所有模板参数:C++模板参数不限于类型)时,尽可能晚地解决泛型方法的实现。 但C#没有采取这种做法。这确实有使编译模型更简单的优点,但它的功能不太强大


(就我个人而言,我希望能够明确地专门化,包括部分专门化,但我也认识到这对在.NET中解决类型的方式有挑战。)

如果您唯一关心的是类型int,为什么不使用类型的一种专门化方法并在执行逻辑之前检查类型?泛型不是模板。不管怎么说,你所问的听起来像是特质,而不是模板专业化。干净的溶液是用C#8制成的。我在编译时发布了一个重载解析的例子。当编译
Method
时,它必须携带什么类型的信息,因此它将选择哪个
专门化
重载?在traits问题中显示了如何在没有官方支持的情况下使用“traits”——不同的traits必须使用针对不同接口的扩展方法来实现,每个“特征”一个。它们也必须通过该接口调用
if(this instanceof Thing<int> x)
  x.Specialisation();
else
  this.Specialisation();