类型T必须是引用类型,以便在使用接口时将其用作参数

Ram*_*ran 5 c# oop generics interface moq

我收到了以下代码的错误

public static Moq.Mock<T> CreateInstanceOfIMock<T>() {
    return new Moq.Mock<T>();
}
Run Code Online (Sandbox Code Playgroud)

我通过使用引用类型解决了它的错误class.请参阅以下代码

public static Moq.Mock<T> CreateInstanceOfIMock<T>() where T : class
{
    return new Moq.Mock<T>();
}
Run Code Online (Sandbox Code Playgroud)

现在我想var mockColorsRepository = new Moq.Mock<IColorsRepository>();通过使用将此代码移动到公共代码中generics.这IColorsRepository是一个interface.所以我做了一个接口参考,T而不是class像下面这样的代码

public static Moq.Mock<T> CreateInstanceOfIMock<T>() where T : interface
{
    return new Moq.Mock<T>();
}
Run Code Online (Sandbox Code Playgroud)

但我得到The type T must be a reference type in order to use it as parameter错误.我怎么可以参考interface,而不是classT.我怎样才能做到这一点?

pok*_*oke 6

class并且struct泛型类型中,constaintsclassstruct用于声明类或结构类型的和声明的含义不同.相反,它们仅限制泛型类型参数是引用类型(class)还是值类型(struct).

所以,当你做where T : class说,T需要有一个类,你是说T必须是引用类型.类似于struct价值类型.

接口本身没有此属性,因此接口可以通过引用类型和值类型实现.因此,将您的类型限制为接口在那里并不真正有意义.

在您的情况下,Moq要求您传递引用类型,因此您需要在所有辅助方法中传递性地继承该类型约束:

public static Moq.Mock<T> CreateInstanceOfIMock<T>()
    where T : class
{
    return new Moq.Mock<T>();
}
Run Code Online (Sandbox Code Playgroud)

这就是创建任何有效类型的模拟所需要做的全部.您可以将其与使用的界面CreateInstanceOfIMock<IColorsRepository>()或任何其他类型一起使用.

当然,在这一点上,该方法并没有真正有意义,因为它不会给你带来任何好处而不仅仅是自己实例化模拟.


Jon*_*eet 5

C#中没有通用约束来强制类型参数是接口.但是,where T : class真的 "其中T是引用类型" -它包含的接口.

如果你想强制实现T接口而不是类,你可以typeof(T)在方法中使用执行时间检查,但在这种情况下,听起来你并不需要将它限制为接口.

我不确定"助手"方法是否特别有用 - 如果你比较:

var mock = Helper.CreateInstanceOfIMock<Foo>();
Run Code Online (Sandbox Code Playgroud)

var mock = new Moq.Mock<Foo>();
Run Code Online (Sandbox Code Playgroud)

或者甚至(除非你在Mock<T>某个地方有另一种类型)只是一个using Moq;指令和

var mock = new Mock<T>();
Run Code Online (Sandbox Code Playgroud)

后者似乎只是可读性和更短......如果你要在你的方法中添加更多逻辑,这是有道理的,但如果它只是调用构造函数,我不认为我会打扰它.