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 "); }

我有一个C#问题,这几天一直困扰着我。我将根据我正在做的事情的抽象描述来解释它。希望它容易理解

假设我们有一个接口

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();
}