有什么办法让现有类型实现一个接口?
比方说,我写了一个真正的踢屁股界面。所以,实际上,我需要使用一些内置类型来实现它们,所以无论使用此接口编写的代码都可以使用内置类型。有什么办法让现有类型实现一个接口?
public interface IKickAss
{
int Yeahhhhhhh() { get; }
}
public static class Woot
{
public int Bar(IKickAss a, IKickAss b)
{
return a.Yeahhhhhhh - b.Yeahhhhhhh;
}
}
// What I'd like to do, sort of.
public partial struct Int32 : IKickAss
{
public int Yeahhhhhhh
{
get
{
return this;
}
}
}
我想这么多次,原因很多。最近的是我为“uint”实现了基数排序,但也创建了一个简单的“IRadixSortable”接口,它需要属性“uint RadixKey {get}”。这意味着我已经基本上重复了排序代码:一次为uint数组,另一次为IRadixSortable数组。我宁愿写一个通过使uint类型实现IRadixSortable。有没有办法做到这一点...也许使用反射?
Haskell可以做到这一点(即类型类可以随时在任何数据类型上实例化),我认为这是它非常强大的一个非常重要的原因。 C#可以真正使用这个功能。也许叫它“扩展接口”:)
那么泛型呢?基本的数字类型都实现了ICopmarable,所以你可以写一个IComparer实现来传递给数组的Sort方法。
或者也许是一种扩展方法。
不支持接口,但可以使用扩展方法做类似的事情。你只是不会得到“合同”
如果你控制实例的创建,你可以继承这个类并在新的继承者类中实现接口。
其他人已经回答了主要问题,但是关于您的特定基数排序场景,您还可以查看.NET Framework中用于比较,散列等的模式类型:允许基数排序方法的用户传入控制排序顺序的对象。例如。使用RadixKey属性创建一个IRadixKeyProvider接口(类似于IHashCodeProvider或IComparer)。
这并不理想,因为用户在每次对基本集合进行基数排序时都必须传入IRadixKeyProvider,而不是在集合类型上一次性定义基数键。 (尽管你可以通过为预定义的类型创建一个重载的排序方法来缓解这个问题,它在内部创建了相关的IRadixKeyProvider,然后转发给更一般的方法。)当然,它没有解决更一般的场景(是的,我也想要类型类!)。但至少可以避免复制基数排序代码。
我看不到内在类型的解决方案,但对于其他类型(即由您或其他人创建的类型),您可以将其子类化并实现您选择的接口。
public interface ISortable
{
// ... whatever you need to make a class sortable
}
public class ExistingType
{
// whatever
}
public class NewType : ExistingType, ISortable
{
// ...
}
除非当然,如果你有权访问现有的类型...然后只是让它实现你的接口。
特别激怒我的是缺乏像IAddable这样的接口,这对于泛型约束来说是天赐之物。 – Promit 2009-04-29 00:22:39
准确! Haskell的类型类可以让你做各种简洁的事情。例如,“add3 x = x + 3”是一个将3加到* any *“Num”类型的函数;这意味着,如果稍后有人过来创建自己的“Num”类型,则该功能将完美地与其一起工作。 – kinghajj 2009-04-29 00:27:07
最好。示例代码。永远。 – 2009-04-29 01:07:34