C#接口对象列表-转换单个元素
我有一个C#问题,这几天一直困扰着我。我将根据我正在做的事情的抽象描述来解释它。希望它容易理解 假设我们有一个接口C#接口对象列表-转换单个元素,c#,list,methods,interface,casting,C#,List,Methods,Interface,Casting,我有一个C#问题,这几天一直困扰着我。我将根据我正在做的事情的抽象描述来解释它。希望它容易理解 假设我们有一个接口 interface iFoo { void a(); } 此外,例如,我有两个类实现了该接口和其中的方法: class bar1 : iFoo { public void a() { Console.WriteLine("bar1"); } public void anotherMethodBar1() { Console.Write("I love "); }
interface iFoo {
void a();
}
此外,例如,我有两个类实现了该接口和其中的方法:
class bar1 : iFoo
{
public void a() { Console.WriteLine("bar1"); }
public void anotherMethodBar1() { Console.Write("I love "); }
}
class bar2 : iFoo
{
public void a() { Console.WriteLine("bar2"); }
public void anotherMethodBar2() { Console.Write("beer"); }
}
每个类还提供一个额外的唯一方法-anotherMethodBar1()和anotherMethodBar2()。现在在我的main()中,我想创建一个列表,其中包含实现我的接口的对象,如下所示:
namespace ExampleFooBar
{
class Program
{
static void Main(string[] args)
{
List<iFoo> fooBarObjects = new List<iFoo>();
fooBarObjects.Add(new bar1());
fooBarObjects.Add(new bar2());
for(int i = 0; i < fooBarObjects.Count; i++)
{
if(fooBarObjects[i].GetType() == typeof(bar1))
{
//Cast element to bar1 and use anotherMethodBar1()
}
if(fooBarObjects[i].GetType() == typeof(bar2))
{
//Cast element to bar2 and use anotherMethodBar2()
}
}
}
}
}
因为C#不了解下面的确切类型,因此此对象的可用方法/函数仅为标准的once加上my a()-方法:
- ()
- 等于()
- GetType()
- GetHashCode()
- ToString()
for(int i = 0; i < fooBarObjects.Count; i++)
{
if(fooBarObjects[i] is bar1)
{
((bar1)fooBarObjects[i]).anotherMethodBar1();
}
else if (fooBarObjects[i] is bar2)
{
((bar2)fooBarObjects[i]).anotherMethodBar2();
}
}
与第一个选项相比,第二个选项被认为是推荐的,因为运行时只需执行一次类型检查(在中作为关键字),而不是两次(是和()
)。您可以使用尝试将其强制转换为类型:
for (int i = 0; i < fooBarObjects.Count; i++)
{
var bar1 = fooBarObjects[i] as Bar1;
if (bar1 != null)
bar1.anotherMethodBar1();
else {
var bar2 = fooBarObjects[i] as Bar2;
if (bar2 != null)
bar2.anotherMethodBar2();
}
}
for(int i=0;i
这是最具可读性且不易出错的强制转换方法。您可以使用扩展方法提取特定类型的项:
var allTheBar1s = fooBarObjects.OfType<bar1>();
foreach(bar1 item in allTheBar1s)
{
//bar1 action
}
//...etc...
现在:
简单地说:)
挑选你所拥有的
for(int i = 0; i < fooBarObjects.Count; i++)
{
if(fooBarObjects[i].GetType() == typeof(bar1))
(fooBarObjects[i] as bar1).anotherMethodBar1();
}
for(int i=0;i
实际上,您在注释“将元素强制转换为bar1并使用anotherMethodBar1”中给出了答案<代码>((bar1)fooBarObjects[i])。anotherMethodBar1()代码>我建议你们阅读以下答案:。谢谢,伙计们!真的很快而且很有帮助。Knaģis是omho的最佳答案,因此我将其标记为。“is”和“as”关键字是解决方案的关键。我曾多次尝试按照Mehmet Ataş的建议施法,但结果如我问题末尾所述。这让我很烦恼,因为我真的不明白为什么会这样。使用“是”可以解决问题,而且效果很好。这里有一个单独的问题,为什么你有一个接口列表,即对象之间的共性,而你感兴趣的是它们的差异。通常,在静态类型语言中对对象类型进行运行时测试表明设计中存在问题,可以使用多态性更好地解决(更优雅且不遗漏角点情况)。在这种情况下,最好使用作为
,然后将结果与null进行比较,以确定是否可以使用它。您使用的是is
,然后使用casting,它将检查类型两次;使用as
只会检查一次类型。最好使用多态性并完全消除任何测试。Matthew Watson,很棒的提示。spender,是的,也可以使用多态性,但在我(真实)的情况下,我发现使用interfaces.Bang更容易。当项目不是bar1
@user2285800时出现NullReferenceException:别忘了检查null
var allTheBar1s = fooBarObjects.OfType<bar1>();
foreach(bar1 item in allTheBar1s)
{
//bar1 action
}
//...etc...
interface IFoo
{
void DoSomething();
...
}
class bar1 : IFoo
{
public void DoSomething()
{
this.anotherMethodBar1();
}
....
}
class bar2 : IFoo
{
public void DoSomething()
{
this.anotherMethodBar2();
}
....
}
foreach(IFoo item in fooBarItems)
{
item.DoSomething();
}
(fooBarObjects[i] as bar1).anotherMethodBar1();
for(int i = 0; i < fooBarObjects.Count; i++)
{
if(fooBarObjects[i].GetType() == typeof(bar1))
(fooBarObjects[i] as bar1).anotherMethodBar1();
}