实现一个缺少new约束的通用接口

7
考虑以下接口:

考虑以下接口:

public interface IFoo
{
    M Bar<M>();
}

尝试使用以下方法实现:
class Foo : IFoo
{
    public M Bar<M>()
    {
        return new M();
    }
}

如果不工作,则编译器会抱怨 M 缺少 new() 约束。

当我添加约束时,如下所示:

class Foo : IFoo
{
    public M Bar<M>() where M : new()
    {
        return new M();
    }
}

这仍然无法解决问题,因为Foo.Bar的限制与接口方法的限制不匹配(而我无法更改它们)。
编译器错误CS0425的文档中提到:

要避免此错误,请确保两个声明中的where子句相同,或显式实现接口。

如果“显式实现接口”是解决方案:我该如何做?

这是因为你需要返回一个新的还是在没有其他返回值时需要返回一些东西?default(M)是否足够好?它返回给定泛型类型的默认值,对于引用类型来说,这是null。否则,您将需要使用表达式树或反射来创建实例。 - Adam Houldsworth
3个回答

8
如果您无法更改接口定义,则必须避免使用new M(); - 而是使用Activator.CreateInstance
class Foo : IFoo
{
    public M Bar<M>()
    {
        return Activator.CreateInstance<M>();
    }
}

当然,如果 M 没有无参数的构造函数,你现在可能会遇到运行时错误,但这是不可避免的(再次强调,因为我们无法更改通用约束条件)。
关于文档:
引用块中写道:“显式地实现接口。”
我认为他们想表达的是,“如果您有一个具有一组通用约束条件的基类方法,并且您想实现具有相同名称的方法具有不同的约束条件的接口,则显式实现是解决该问题的一种方式。”

感谢您解释文档:您可能是对的。我一直在思考“文档解释了我做错了什么并展示了摆脱困境的方法”,这让我走上了错误的道路。 - mkluwe

6
实现接口并不是解决方案。编译器只是在告诉你,如果你需要一个带有这个约束条件的通用方法Bar,那么就要显式地实现接口,以便两个版本的Bar都可以共存。但很明显,这不是你要找的解决方案。
唯一的解决方案是:
1. 在接口中实现泛型类型约束。 2. 通过反射实例化新的M:Activator.CreateInstance,并付出在编译时失去类型安全性的代价;没有任何强制规定M必须具有无参数构造函数。

没有强制要求M是您可以实例化的类型,它可能是一个接口。 - Adam Houldsworth
@AdamHouldsworth 好的,是的,任何不可实例化的类型都缺少可用的无参构造函数。我没看出你试图做出的区别。 - InBetween
没有区别,只是指出没有无参构造函数真的不是最大的问题 - 更多是一种观察。这只是提醒我为什么我不太喜欢创建或使用这样的接口。 - Adam Houldsworth
@AdamHouldsworth 哦,好的,明白了。 - InBetween

0

您可以通过右键单击应该实现它的类中的接口并选择“显式实现”来生成显式接口实现。方法名称应以接口名称为前缀。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接