在C#如何获得不同的IEqualityComparer<;T>;实例,如果泛型类型实现接口

在C#如何获得不同的IEqualityComparer<;T>;实例,如果泛型类型实现接口,c#,generics,template-specialization,C#,Generics,Template Specialization,我有一个无约束泛型类型的泛型方法。如果类型T实现了一个接口,我需要获得一个不同的IEqualityComparer 代码大致如下所示: public SomeState MergeCollection<T>( ICollection<T> thisValue, ICollection<T> otherValue, SomeStrategy strategy = SomeStrategy.Default, IEquality

我有一个无约束泛型类型的泛型方法。如果类型T实现了一个接口,我需要获得一个不同的IEqualityComparer

代码大致如下所示:

public SomeState MergeCollection<T>(
    ICollection<T> thisValue, 
    ICollection<T> otherValue, 
    SomeStrategy strategy = SomeStrategy.Default, 
    IEqualityComparer<T> comparer = null)
{
    comparer = comparer ?? GetComparer<T>(strategy);
    // code using comparer
}

public IEqualityComparer<T> GetComparer<T>(SomeStrategy strategy)
{
    if(typeof(IMerge).IsAssignableFrom(typeof(T)))
    {
        return GetMergeComparer<T>(strategy);
    }
    else
    {
        return EqualityComparer<T>.Default;
    }
}
publicsomestate合并集合(
i收集此值,
i收集其他值,
SomeStrategy=SomeStrategy.Default,
IEqualityComparer比较器=空)
{
比较器=比较器??获取比较器(策略);
//使用比较器的代码
}
公共IEqualityComparer GetComparer(SomeStrategy)
{
if(typeof(IMerge).IsAssignableFrom(typeof(T)))
{
返回GetMergeComparer(策略);
}
其他的
{
返回EqualityComparer.Default;
}
}
似乎是模板专业化的典型案例,但据我所知,C#不支持此类功能。我还考虑过静态类实现一种策略模式,以交换用于获取比较器的函数,但是静态类将为所有类型实现,因此类型方法字典查找是必要的。为此生成IL代码似乎是万不得已的办法,考虑到代码的使用量并不是很高,不值得为此付出努力

如果T实现了IMerge,那么改变有问题的方法的行为从而得到特例的最佳方法是什么?我这样问是因为理论上,如果行为在运行时不会改变,应该可以在编译时或至少在初始化时(静态构造函数)定义行为

  • 我认为你现有的代码没有任何问题。就我个人而言,我会保持原样

    在您有证据表明它的性能关键是过早优化之前,我会对此进行优化

  • 如果确实要缓存比较结果,可以使用以下方法:

    static class MergeComparerHelper<T>
    {
        static bool SupportsMerge = typeof(IMerge).IsAssignableFrom(typeof(T));
    }
    
    静态类合并比较器帮助
    {
    静态bool SupportsMerge=typeof(IMerge).IsAssignableFrom(typeof(T));
    }
    
    这使用了一个事实,即每个泛型实例化都有自己的静态字段。您可以为此使用私有嵌套类

    但是请注意,这仍然会产生运行时调度的成本,因为.NET抖动的当前实现不会为不同的引用类型
    T
    s生成专门的实现


  • 您现有的代码有什么问题?虽然您可以将
    typeof(IMerge).IsAssignableFrom(typeof(T))
    缓存在静态
    ConditionalWeakDictionary
    中,但这不太值得费事,也可能不会提高那么多性能。我在最后添加了说明。它使用反射来改变编译时已知的行为,因此原则上它不被认为是一个好的代码。问题是类本身不是泛型的,只是方法是泛型的。我想这将需要创建一个单独的通用静态比较器工厂类,该类具有用于获取比较器的属性。似乎很难:)我将保留1,但2看起来是一个合理的方法,我肯定会保留书签,以用于更复杂/需要更多优化的通用类/方法专业化的特殊情况。它还显示了C#在这一领域的局限性。我会等几天,以防万一。谢谢你的帮助。