C#:接口中的枚举

bwe*_*rks 18 c# generics enums interface

我已经看到了几个与此问题类似的线索,但他们都没有真正回答我想问的问题.

对于初学者来说,不幸的是我正在使用现有的API代码,所以很遗憾,虽然可能有更好的方法来做我所要求的事情,但是由于向后兼容性不同,我已经被锁定了. -negotiable.

我有一个响应类,当前包含一个错误代码和字符串描述的枚举.错误代码定义了一组相当不错且完整的响应,这些响应在语义上与使用它们的操作非常相似.

不幸的是,我现在必须为一组类似的API对象添加不同的工作流程,这将需要一个字符串描述,这很好,但也是一个包含一组完全不相关的错误代码的枚举错误代码.错误代码(以及对象模型的其他方面)将在许多相同的类中使用,因此最好让接口运行以便我可以通过相同的框架运行对象.

这里的目的是签订一份合同,上面写着"我有一个错误代码,以及该错误代码的描述".

但是,据我所知,没有办法将项目添加到界面,如

public interface IError
{
    enum ErrorCode;
    string Description;
}
Run Code Online (Sandbox Code Playgroud)

也没有办法表达

public interface IError<T> where T: enum
{
    T ErrorCode;
    string Description;
}
Run Code Online (Sandbox Code Playgroud)

以前每个人都遇到这样的事情吗?

Jon*_*eet 14

是的,我遇到了这个问题.不是在这种特殊情况下,而是在其他Stack Overflow问题中,就像这个问题一样.(我不会投票将这个作为副本关闭,因为它略有不同.)

可以表达你的通用接口-只是没有在C#.你可以在IL中做到没有问题.我希望在C#5中可以删除限制.就我所见,C#编译器实际上正确地处理了约束.

如果你真的想作为一个选项,你可以使用类似于Unconstrained Melody中的代码,这是一个我已经得到的库,它使用这种难以生成的约束来暴露各种方法.它有效地使用IL重写 - 它很粗糙,但它适用于UM,也可能适合你.你可能想把接口放到一个单独的程序集中,这有点尴尬.

当然,你可以让你的界面T : struct改为......它不是理想的,但它至少会在某种程度上限制这种类型.只要你能确保它没有被滥用,那就行得相当好.


Joe*_*ler 8

正如Jon Skeet所提到的,基本IL支持将泛型约束为枚举,但C#不允许您利用它.

但是,F#确实允许这种约束.此外,如果接口是在F#中定义的,则约束将在实现接口的C#代码中强制执行.如果您愿意在解决方案中混合语言,那么这样的事情应该可以正常工作:

type IError<'T when 'T :> System.Enum and 'T : struct> =
    abstract member Error : 'T
    abstract member Description : string
Run Code Online (Sandbox Code Playgroud)

如果将它放在F#项目中并从C#项目引用它,那么实现该接口的C#代码将导致C#编译器错误,因为任何尝试将其与非枚举类型一起使用.