C# 使用多个类/接口进行列表筛选
基本上,我有一个对象列表,其中每个对象可能实现一组不同的接口:C# 使用多个类/接口进行列表筛选,c#,generics,interface,C#,Generics,Interface,基本上,我有一个对象列表,其中每个对象可能实现一组不同的接口: List<BaseObject> objects; class BaseObject { public void DoStuff(); } interface IX { void DoX(); } interface IY { void DoY(); } interface IZ { void DoZ(); } 列出对象; 类基类对象 { 公共无效DoStuff(); } 接口九 { void
List<BaseObject> objects;
class BaseObject
{
public void DoStuff();
}
interface IX
{
void DoX();
}
interface IY
{
void DoY();
}
interface IZ
{
void DoZ();
}
列出对象;
类基类对象
{
公共无效DoStuff();
}
接口九
{
void DoX();
}
界面IY
{
void DoY();
}
接口IZ
{
void-DoZ();
}
我想这样写:
foreach(var obj in objects.OfType<BaseObject and IX>)
{
obj.DoStuff();
obj.DoX();
}
foreach(objects.OfType中的var obj)
{
对象DoStuff();
obj.DoX();
}
(例如,我对BaseObject和IX类型的对象执行特定算法,而不必在那里进行类型转换)
可以用C#做吗?
最优雅的解决方案是什么
我可以这样做:
foreach(var obj in objects.OfType<IX>)
{
var baseobj = (BaseObject)obj.DoStuff();
obj.DoX();
}
foreach(objects.OfType中的var obj)
{
var baseobj=(BaseObject)obj.DoStuff();
obj.DoX();
}
但我觉得很难看
我可能需要对实现接口IX和接口IZ的类型应用特定的操作
foreach(var obj in objects.OfType<BaseType and IX and IZ>)
{
obj.DoStuff();
obj.DoX();
obj.DoZ();
}
foreach(objects.OfType中的var obj)
{
对象DoStuff();
obj.DoX();
obj.DoZ();
}
使用这些类和接口
List<BaseObject> objects;
class BaseObject
{
public void DoStuff();
}
interface IX
{
public void DoX();
}
interface IY
{
public void DoY();
}
interface IZ
{
public void DoZ();
}
class X : BaseObject, IX { }
class Y : BaseOjbect, IY { }
class Z : BaseObject, IZ { }
class XY : BaseObject, IX, IY { }
这应该符合你的要求
根据您的评论进行更新
foreach (var o in objects)
{
o.DoStuff();
if (o is IX and o is IY)
{
// do something different only for XY
}
else if (o is IX)
((IX)o).DoX(); //executed on class X
else if (o is IY)
((IY)o).DoY(); //excuted on class Y
else if (o is IZ)
((IZ)o).DoZ(); //excuted on class Z
}
已更新无类型转换
需要另一个接口。(此外,DoStuff()应位于所有IX、IY、IZ上)
接口IXY:IX,IY{}
//这个IXY可以是var,但只需将其强类型化即可
foreach(对象中的IXY o。类型(IXY)
.Cast())
{
o、 DoStuff();
o、 DoX();
o、 DoY();
}
你也可以做一些疯狂的事情,比如:
foreach(objects.OfType()中的var obj)
第()类
第()类
.选择(o=>new
{
AsIX=(IX)o,
AsIY=(IY)o,
AsIZ=(IZ)o
})
{
obj.AsIX.DoX();
obj.AsIY.DoY();
obj.AsIZ.DoZ();
}
在DoStuff内。您能做什么
if (this is IX) { (this as IX).DoX(); }
…并对其他接口执行此操作。不可能完全按照您的要求执行
这是你能做的
首先,您希望只对实现了IX
、IY
和IZ
的类型进行操作,然后只需将您的of type
方法链接在一起。of type
将为您筛选列表:
foreach (var obj in objects.OfType<IX>().OfType<IY>().OfType<IZ>()) {
避免大量强制转换和类型测试的最简洁的方法是引入一个扩展方法来为您处理它
试试这个:
public static void DoAs<T>(this object @this, Action<T> action)
where T : class
{
var t = @this as T;
if (t != null)
{
var a = action;
if (a != null)
{
a(t);
}
}
}
您的第一个/中间循环不需要任何新的扩展方法,因为我认为这应该足够简单:
foreach(var obj in objects.OfType<IX>())
{
(obj as BaseObject).DoStuff();
obj.DoX();
}
foreach(objects.OfType()中的var obj)
{
(obj作为BaseObject).DoStuff();
obj.DoX();
}
我希望这有帮助。一种可能的方法是使用动态
:
foreach(var xz in objects.Where(o => o is IX && o is IZ).Select(o => (dynamic)o))
{
xz.DoStuff();
xz.DoX();
xz.DoZ();
}
foreach(var xz in objects.Where(o => o is IX && o is IZ))
{
xz.DoStuff();
((IX)xz).DoX();
((IZ)xz).DoZ();
}
当然,如果不想使用dynamic
,您仍然可以进行强制转换:
foreach(var xz in objects.Where(o => o is IX && o is IZ).Select(o => (dynamic)o))
{
xz.DoStuff();
xz.DoX();
xz.DoZ();
}
foreach(var xz in objects.Where(o => o is IX && o is IZ))
{
xz.DoStuff();
((IX)xz).DoX();
((IZ)xz).DoZ();
}
不是真的,我只想为实现X和Y接口的对象执行一个特定的算法。更新后,你说得很对,但不幸的是,你的解决方案涉及大量类型转换,这正是我想要回避的:(我已经按照您的命令进行了更新。为什么您要求在循环中对每个的变量进行类型转换,这似乎不必要地复杂(但可能)。我想这在C中是不可能的,否则在ATM中就是这样写的。@jbeuler,是的,这是一个折衷:)
foreach(var obj in objects.OfType<IX>())
{
(obj as BaseObject).DoStuff();
obj.DoX();
}
foreach(var xz in objects.Where(o => o is IX && o is IZ).Select(o => (dynamic)o))
{
xz.DoStuff();
xz.DoX();
xz.DoZ();
}
foreach(var xz in objects.Where(o => o is IX && o is IZ))
{
xz.DoStuff();
((IX)xz).DoX();
((IZ)xz).DoZ();
}