我有一个对通用类型进行操作的类:
public class Operation<I> where I : IAnimal
并且我将IAnimal
定义如下:
public interface IAnimal
{
string Name { get; }
}
我将类定义如下:
public class Dog : IAnimal
{
string Name { get; private set; }
public Dog(string name)
{
Name = name;
}
}
如果我想在Dog
类中使用Operation
,则由于Dog
类没有无参数构造函数,因此我将策略模式用于以下方面:
public interface IConstructor
{
IAnimal Construct(string name);
}
public class DogConstructor : IConstructor
{
IAnimal Construct(string name)
{
return new Dog(name);
}
}
public class Operation<I> where I : IAnimal
{
public Operation() : this(new DogConstructor())
{ }
public Operation(IConstructor constructor)
{
I animal = constructor.Construct("myDog"); // <<<<<<<< Error here!
}
}
在市场上,我收到Cannot implicitly convert type 'IAnimal' to 'I'. An explicit conversion exists (are you missing a cast?)
当然,如果我像I animal = (I)constructor.Construct("myDog");
一样,所有方法都可以。但是,我想知道为什么我有where I : IAnimal
时需要投射。
答案 0 :(得分:2)
但是,我想知道为什么我在
I : IAnimal
所在的位置时需要进行投射。
是的,您确实保证I
将是IAnimal
或IAnimal
本身的子类,但是Construct
会返回什么? Construct
可能返回与I
不同的子类。
无论何时使用泛型,都应记住泛型参数类型是由类/方法的客户端代码提供的,而不是类/方法。在这里,如果没有传递参数,则通过使用I
强制Dog
成为DogConstructor
。如果执行此操作,则可能意味着泛型在这里不合适。尝试删除它:
public class Operation
{
public Operation() : this(new DogConstructor())
{ }
public Operation(IConstructor constructor)
{
IAnimal animal = constructor.Construct("myDog");
}
}
现在,如果您坚持使用泛型,则不能默认使用DogConstructor
,而IConstructor
也应该是泛型的:
public interface IConstructor<T> where I: IAnimal
{
T Construct(string name);
}
public class DogConstructor : IConstructor<Dog>
{
Dog Construct(string name)
{
return new Dog(name);
}
}
public class Operation<I> where I : IAnimal
{
public Operation(IConstructor<I> constructor)
{
I animal = constructor.Construct("myDog");
}
}
public class DogOperation: Operation<Dog> {
public DogOperation() : base(new DogConstructor()) {}
}
因为Dog类没有无参数的构造函数
另一种解决方案可能是约束I
,使其必须具有无参数构造函数,然后将其添加到Dog
:
class Operation<I> where I : IAnimal, new() {
答案 1 :(得分:2)
问题是编译器不知道您要代替I传递什么类。假设您创建另一个类,该类从Animal派生而来,类似于Cat。现在,您将Cat代替I传递给了Operation,按照代码可以。但是Constructor.Construct(“ myDog”)返回的Dog是Cat的同级兄弟,无法解析为Cat。所以错误会来。查看代码
public interface IAnimal
{
string Name { get; }
}
public class Dog : IAnimal
{
public string Name { get; set; }
public Dog(string name)
{
this.Name = name;
}
}
public class Cat : IAnimal
{
public string Name { get; set; }
public Cat(string name)
{
this.Name = name;
}
}
public class Operation<I> where I : IAnimal
{
public Operation() : this(new DogConstructor())
{ }
public Operation(IConstructor constructor)
{
I animal = constructor.Construct("myDog"); // <<<<<<<< Error here!
}
}
检查以下代码。您正在传递Cat,并且希望将其与Dog映射。那行不通。
public class XYZ
{
public void MyMethod()
{
var obj = new Operation<Cat>();
}
}
如果您知道它将构造方法。Construct(“ myDog”)返回animal,然后将I替换为IAnimal。这样,编译器就可以确定要在其中设置从构造函数.Construct(“ myDog”)返回的对象的引用
public class Operation<I> where I : IAnimal
{
public Operation() : this(new DogConstructor())
{ }
public Operation(IConstructor constructor)
{
IAnimal animal = constructor.Construct("myDog"); // <<<<<<<< Error here!
}
}
答案 2 :(得分:1)
问题在于无法保证您的**Table Online**
Col1 Col2 Score |
a b 1 |
a c 2 |
a d 3 |
f e 4 |
**Table Offline**
Col1 Col2 Score |
a m 10 |
a c 20 |
a d 30 |
t k 40 |
**Table Output**
Col1 Col2 Online.Score Offline.Score |
a c 2 20 |
a d 3 30 |
a b 1 |
a m 10 |
返回与IConstructor
相同的类。您可以拥有一个I
,并将一个Operation<Cat>
传递给构造函数。
您也可以通过使DogConstructor
通用来解决此问题,并使Operation构造函数接收IConstructor
。
答案 3 :(得分:1)
我遇到了同样的问题,并且我使用了Activator.CreateInstance(Type type,params object [] args)
static void Main()
{
var operation = new Operation<Dog>("Jack");
Console.WriteLine(operation.Animal.Name);
Console.ReadLine();
}
public interface IAnimal
{
string Name { get; }
}
public class Dog : IAnimal
{
public string Name { get; private set; }
public Dog()
{
}
public Dog(string name)
{
Name = name;
}
}
public class Operation<T> where T : IAnimal, new()
{
public T Animal { get; private set; }
public Operation()
{
Animal = new T();
}
public Operation(params object[] args)
{
Animal = (T)Activator.CreateInstance(typeof(T), args);
}
}