经过长时间的研究,我找到了一个简单易懂的解释方法。至少对我来说很清晰。
想象一下我们有一个签名为这样的方法。
public static T[] Sort(T[] array, IComparator<T> comparator)
{
...
}
IComparator
的实现:
public class IntegerComparator : IComparator<int> { }
然后我们可以像这样编写代码:
var sortedIntegers = Sort(integers, new IntegerComparator());
我们可以改进这段代码,首先创建一个Dictionary<Type, IComparator>
并填充它:
var comparators = new Dictionary<Type, IComparator>()
{
[typeof(int)] = new IntegerComparator(),
[typeof(string)] = new StringComparator()
}
Redesigned IComparator interface so that we could write like above
public interface IComparator {}
public interface IComparator<T> : IComparator {}
接下来让我们重新设计Sort
方法的签名
public class SortController
{
public T[] Sort(T[] array, [Injectable]IComparator<T> comparator = null)
{
...
}
}
正如您所了解的,我们将注入 IComparator<T>
,并编写以下代码:
new SortController().Sort<int>(integers, (IComparator<int>)_somparators[typeof(int)])
正如你已经猜到的那样,除非我们概述实现并添加Dictionary<Type, IComparator>
,否则此代码将无法适用于其他类型。
请注意,我们将只在运行时看到异常
现在想象一下,如果编译器在构建期间为我们完成了这项工作,并且如果它找不到具有相应类型的比较器,则抛出异常。
为此,我们可以帮助编译器并添加一个新关键字,而不是使用属性。我们的Sort
方法将如下所示:
public static T[] Sort(T[] array, implicit IComparator<T> comparator)
{
...
}
并实现具体比较器的代码:
public class IntegerComparator : IComparator<int> implicit { }
请注意,我们使用关键字“implicit”,在此之后编译器将能够执行我们上面编写的常规工作,并且异常将在编译时抛出。
var sortedIntegers = Sort(integers);
var sortedStrings = Sort(strings);
给这种实现方式起个名字,类型类
public class IntegerComparator : IComparator<int> implicit { }
我希望我理解得正确,并且能够清楚地解释。
附注:这段代码并不打算运行。
Show a => MyClass a
这样的约束接口吗?以及能够在容器类型上工作的仿函接口? - epsilonhalbeclass Eq
吗?还是我理解错了什么。我对Haskell不太了解,因此我想看到一个优点的例子。 - giokoguashvili