我有很多单元测试,几乎测试相同的行为.但是,数据类型会发生变化
我正在尝试创建一个可以采用任何数据类型的泛型方法.我尝试制作输入参数var但不允许这样做.另外,查看c#泛型,但通常会处理列表.
Jus*_*gan 52
您可以将参数设为object:
public void DoSomething(object arg)
{
//...
Run Code Online (Sandbox Code Playgroud)
或者你可以做我喜欢的事情并制作一个通用的方法:
public void DoSomething<T>(T arg)
{
//...
Run Code Online (Sandbox Code Playgroud)
通用方法有两个主要优点,我将举例说明它们有用的原因:
arg,您仍然可以访问它.相反,该object方法有一些重要的缺点:
arg一个对象object,你就只能做任何对象所能做的事情.object参数传递,则变量将被加框,这意味着性能受到影响.这不是一个巨大的打击,但如果你DoSomething连续几次打电话,你可能会开始感受它.向泛型方法添加类型约束允许您限制方法,使其仅接受某些类型.为什么这有用?因为即使您不了解或关心您正在使用的具体类型,您现在也可以了解它,并且您可以使用该信息.
请考虑以下设置:
public interface IAnimal
{
void Move();
}
public class Duck : IAnimal
{
public void Move()
{
Console.WriteLine("Flying");
}
}
public class Fish : IAnimal
{
public void Move()
{
Console.WriteLine("Swimming");
}
}
public class Ant : IAnimal
{
public void Move()
{
Console.WriteLine("Walking");
}
}
Run Code Online (Sandbox Code Playgroud)
由于我们有一个IAnimal接口,我们可以编写针对以下任何实现的通用方法IAnimal:
public class Program
{
static void DoMove<T>(T animal) where T : IAnimal
{
animal.Move();
}
public static void Main(string[] args)
{
Duck duck = new Duck();
Fish fish = new Fish();
Ant ant = new Ant();
DoMove<Duck>(duck);
DoMove<Fish>(fish);
DoMove<Ant>(ant);
}
}
Run Code Online (Sandbox Code Playgroud)
运行它:http://rextester.com/GOF1761
当我们编写DoMove方法时,我们不关心它的参数animal是a Duck,a Fish,an Ant还是其他任何东西.我们所关心的只是打电话animal.Move().由于我们使用了where T : IAnimal约束,编译器知道我们需要知道的一切:
animal属于类型T.T,它都实现了IAnimal.IAnimal都有一个Move()方法.animal.Move().(顺便说一下,是的,我们可以只写DoMove的static void DoMove(IAnimal animal),但这是另一个讨论.)
很好,但让我们更进一步.在许多情况下,您可以调用泛型方法而无需指定其类型参数.这称为类型推断,除了为您节省一些输入外,在对不同类型的对象执行相同操作时也很有用.
public static void Main(string[] args)
{
IAnimal[] animals = new IAnimal[]
{
new Duck(),
new Fish(),
new Ant()
};
foreach (IAnimal animal in animals)
{
DoMove(animal);
}
}
Run Code Online (Sandbox Code Playgroud)
运行它:http://rextester.com/OVKIA12317
您只需编写DoMove<T>一次该方法,并且可以在任何类型上调用它,IAnimal而无需提供更具体的类型.每次都会调用相应的Move版本,因为DoMove<T>它可以推断出要使用的类型T.当你打电话时DoMove(duck),.NET明白你真正的意思DoMove<Duck>(duck),然后调用类Move上的方法Duck.
您可以将其object作为参数类型.或许更好的是使用泛型:
void MyMethod<T>(T parm) { ... }
Run Code Online (Sandbox Code Playgroud)
这样,参数实际上是用户传入的类型 - 它不像box object和value类型一样.