通过扩展方法进行模板专业化

时间:2018-11-26 14:53:19

标签: c#

在C#中,我想让我的通用类的方法以类似于explicit template specialization

的方式以不同的方式运行

我从a related post看到,使用扩展名在C#中可能发生这种情况,但是我的代码无法正常工作:我想要Thing<int>::Method()的一种行为,而当{{1 }}是<T>以外的任何东西。

我有

<int>

但这输出

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();
    }
}

而不是

Thing<T> specialization
Thing<T> specialization
Thing<T> specialization
Thing<int> specialization

一个显而易见的问题:“为什么不只叫Thing<T> specialization Thing<T> specialization Thing<int> specialization Thing<int> specialization 而不叫Specialization<T>?”希望通过包含接口类来解决-我正试图适应框架。

我可以看到MethodSpecialization<T>的匹配项,但令我惊讶的是后者没有被视为更好的匹配项!

2 个答案:

答案 0 :(得分:2)

不幸的是,当您调用Method()时,它以Thing<T>的身份运行,而不知道它是Thing<int>。您可以使用反射来找出答案,或者(更好的主意):

if(this instanceof Thing<int> x)
  x.Specialisation();
else
  this.Specialisation();

或者,您可以将Method()声明为virtual并使用IntThing : Thing<int>创建override void Method(){...}

答案 1 :(得分:1)

编译包含方法时,对this.Specialization<T>();的调用已解决。那时T就是一切。

某些具有通用支持的语言(例如C ++)在所有类型参数(或在C ++情况下,所有模板参数:在C ++模板参数中不限于类型)时,都尽可能晚地解决了通用方法的实现。

但是C#不采用这种方法。这样做确实具有使编译模型更简单的优点,但是功能却不那么强大。

(我个人希望具有显式专业化的能力,包括部分专业化,但是我也认识到这对.NET中解析类型的方式带来了挑战。)