这就是我想在C#中做的事情(在class Helper
内 - 没有通用参数),
List<AbstractClass<dynamic>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<dynamic>) thing);
}
此助手类将使用AbstractClass<>
个对象并返回特定泛型类型的AbstractClass<>
。 AbstractClass<T>
包含许多函数,这些函数返回T
/ T
,如public T Invoke()
。
对于Helper类T
,事先无法知道。 Add<T>(.. thing)
函数不在T
类中。
要在Helper类的函数中使用,
foreach(var c in data.Where(x => ...))
{
// public T Invoke() { ... } function within AbstractClass<T>
var b = c.Invoke();
// logic
}
这也失败了,
List<AbstractClass<object>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<object>) thing);
}
现在我想我可以拥有,
List<dynamic> data; // or List<object> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add(thing);
}
但我希望List命名数据只有像
这样的元素的约束ConcreteClass : AbstractClass<OtherClass>
所以我们知道有一个public T Invoke()
函数,但我们不知道它返回了什么。这有助于避免错误拼写错误的Invocke并且只在运行时知道。
我想避免每次调用dynamic
来调用返回泛型类型T的函数
答案 0 :(得分:1)
要做你想做的事,你需要使用Contravariant interface
public class Program
{
static void Main()
{
var m = new Helper();
m.Add(new ConcreteClass());
m.Process();
}
class Helper
{
List<IAbstractClass<OtherClassBase>> data = new List<IAbstractClass<OtherClassBase>>();
public void Add(IAbstractClass<OtherClassBase> thing)
{
this.data.Add(thing);
}
public void Process()
{
foreach(var c in data.Where(x => x.ShouldBeProcessed()))
{
var b = c.Invoke();
Console.WriteLine(b.Question);
var castData = b as OtherClass;
if (castData != null)
Console.WriteLine(castData.Answer);
}
}
}
public interface IAbstractClass<out T>
{
bool ShouldBeProcessed();
T Invoke();
}
abstract class AbstractClass<T> : IAbstractClass<T>
{
public bool ShouldBeProcessed()
{
return true;
}
public abstract T Invoke();
}
class ConcreteClass : AbstractClass<OtherClass>
{
public override OtherClass Invoke()
{
return new OtherClass();
}
}
class OtherClassBase
{
public string Question { get { return "What is the answer to life, universe, and everything?"; } }
}
class OtherClass : OtherClassBase
{
public int Answer { get { return 42; } }
}
}
你不需要告诉Add
你传递的类是什么类,重要的是它是从指定的类型派生出来的。您可以执行public void Add(IAbstractClass<object> thing)
并且每个类都可以工作,但Invoke()
只返回foreach循环内的对象。
你需要弄清楚你希望Invoke()
返回的派生类最多的是什么,这就是你在列表中设置的类型。
答案 1 :(得分:0)
也许这对你有用:
public class Program
{
static void Main()
{
var m1 = new Helper<OtherClass>();
m1.Add(new ConcreteClass());
var m2 = new Helper<int>();
m2.Add(new ConcreteClass2());
}
class Helper<T>
{
List<AbstractClass<T>> data = new List<AbstractClass<T>>();
public void Add<T1>(T1 thing) where T1 : AbstractClass<T>
{
this.data.Add(thing);
}
}
class AbstractClass<T> { }
class OtherClass { }
class ConcreteClass : AbstractClass<OtherClass> { }
class ConcreteClass2 : AbstractClass<int> { }
}