在 C# 中解析泛型方法参数
Resolving generic method parameters in C#
我有一个方法重载了 3 次,功能完全相同,唯一的变化是一个参数,它是一个具体类型的列表。
private void _doWork(string name, List<TargetItem> members)
{
foreach(var member in members)
{
_doExtraWork(member.TimeToWork);
}
}
private void _doWork(string name, List<NonTargetItem> members)
{
foreach(var member in members)
{
_doExtraWork(member.TimeToWork);
}
}
这里要知道的是列表中的 2 个 classes 来自 WSDL 定义。迭代中的操作针对共享成员,因为它们派生自相同的基 class,但是这种继承在 WSDL 中被抽象化。
我试过这样做 -
private void _doWork<T>(string name, List<T> members)
{
var commonList = new List<>(); /// what type should I use here?
if(typeof (T) == typeof(TargetItem))
{
commonList = members; // assume equal to means copying members to commonList with type conversion
}
if(typeof (T) == typeof(NonTargetItem))
{
commonList = members;
}
foreach(var member in commonList)
{
_doExtraWork(member.TimeToWork);
}
}
这是处理问题和重构此通用代码的正确方法,还是我在这里遗漏了什么?
你可以这样做
private static void _doWork<T>(string name, T members) where T : IEnumerable
{
foreach(var member in members)
{
_doExtraWork(member.TimeToWork);
}
}
在您的调用代码中
_doWork("sdfsd", new List<TargetItem>()); // here just as example I am passing new instance
_doWork("sdfsd", new List<NonTargetItem>()); // here just as example I am passing new instance
因为 List<T>
是 IEnumerable<T>
类型,而 IEnumerable<T>
又是 IEnumerable 类型。您可以在泛型函数中添加 IEnumerable 泛型约束。这样,您就不必在泛型函数中进行类型检查。
如果您想实现单个 doExtraWork 方法,那么您需要为 TargetItem 和 NonTargetItem 使用 CommonType。您可以使用如下所示的适配器模式解决此问题
Interface IItem
{
int TimeToWorkAdapt {get;}
}
//Now create a wrapper class for TargetItem and NonTargetItem
Class TargetItemAdapt : TargetItem,IItem
{
public int TimeToWorkAdapt
{
get { base.TimeToWork;}
}
}
Class NonTargetItemAdapt : NonTargetItem,IItem
{
public int TimeToWorkAdapt
{
get { base.TimeToWork;}
}
}
// write a generic function which wrap calls to your do extra work method but with generic constriants to interface
private static void _doExtraWork<T>(T members) where T : IItem
{
_doExtraWork(member.TimeToWorkAdapt);
}
// In your Main program...now use our wrapper classes
_doWork("sdfsd", new List<TargetItemAdapt>()); // here just as example I am passing new instance
_doWork("sdfsd", new List<NonTargetItemAdapt>()); // here just as example I am passing new instance
我选择了来电者的垂头丧气
_doWork("Target", Object.TargetItems.ToList<BaseClass>());
_doWork("NonTarget", Object.NonTargetItems.ToList<BaseClass>());
我有一个方法重载了 3 次,功能完全相同,唯一的变化是一个参数,它是一个具体类型的列表。
private void _doWork(string name, List<TargetItem> members)
{
foreach(var member in members)
{
_doExtraWork(member.TimeToWork);
}
}
private void _doWork(string name, List<NonTargetItem> members)
{
foreach(var member in members)
{
_doExtraWork(member.TimeToWork);
}
}
这里要知道的是列表中的 2 个 classes 来自 WSDL 定义。迭代中的操作针对共享成员,因为它们派生自相同的基 class,但是这种继承在 WSDL 中被抽象化。
我试过这样做 -
private void _doWork<T>(string name, List<T> members)
{
var commonList = new List<>(); /// what type should I use here?
if(typeof (T) == typeof(TargetItem))
{
commonList = members; // assume equal to means copying members to commonList with type conversion
}
if(typeof (T) == typeof(NonTargetItem))
{
commonList = members;
}
foreach(var member in commonList)
{
_doExtraWork(member.TimeToWork);
}
}
这是处理问题和重构此通用代码的正确方法,还是我在这里遗漏了什么?
你可以这样做
private static void _doWork<T>(string name, T members) where T : IEnumerable
{
foreach(var member in members)
{
_doExtraWork(member.TimeToWork);
}
}
在您的调用代码中
_doWork("sdfsd", new List<TargetItem>()); // here just as example I am passing new instance
_doWork("sdfsd", new List<NonTargetItem>()); // here just as example I am passing new instance
因为 List<T>
是 IEnumerable<T>
类型,而 IEnumerable<T>
又是 IEnumerable 类型。您可以在泛型函数中添加 IEnumerable 泛型约束。这样,您就不必在泛型函数中进行类型检查。
如果您想实现单个 doExtraWork 方法,那么您需要为 TargetItem 和 NonTargetItem 使用 CommonType。您可以使用如下所示的适配器模式解决此问题
Interface IItem
{
int TimeToWorkAdapt {get;}
}
//Now create a wrapper class for TargetItem and NonTargetItem
Class TargetItemAdapt : TargetItem,IItem
{
public int TimeToWorkAdapt
{
get { base.TimeToWork;}
}
}
Class NonTargetItemAdapt : NonTargetItem,IItem
{
public int TimeToWorkAdapt
{
get { base.TimeToWork;}
}
}
// write a generic function which wrap calls to your do extra work method but with generic constriants to interface
private static void _doExtraWork<T>(T members) where T : IItem
{
_doExtraWork(member.TimeToWorkAdapt);
}
// In your Main program...now use our wrapper classes
_doWork("sdfsd", new List<TargetItemAdapt>()); // here just as example I am passing new instance
_doWork("sdfsd", new List<NonTargetItemAdapt>()); // here just as example I am passing new instance
我选择了来电者的垂头丧气
_doWork("Target", Object.TargetItems.ToList<BaseClass>());
_doWork("NonTarget", Object.NonTargetItems.ToList<BaseClass>());