2013-06-12 5 views
1

지난 며칠 동안 나를 괴롭 히고있는 C# 문제가 있습니다. 내가하고있는 것에 대한 추상적 인 묘사에 기초하여 그것을 설명하려고 노력할 것이다. 따르기 쉽기를 바랍니다.C# 인터페이스 개체 목록 - 단일 요소 캐스팅

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

각 클래스는 또한 제공 :)

은의 우리가 내가 예를 들어,이 인터페이스를 구현하는이 개 클래스를 추가하는 인터페이스

interface iFoo { 
    void a(); 
} 

그 안에있는 방법이 있다고 가정 해 봅시다 추가 고유 메소드 - anotherMethodBar1() 및 anotherMethodBar2(). 이제 내() 나는이처럼 내 인터페이스를 구현하는 객체가 포함 된 목록을 만들려면 주 :

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

을 당신은 (I 각 개체의 (인터페이스에 포함되지 않음) 자신의 메소드를 호출 할 볼 수 있듯이 클래스에 기반하여 우리는 anotherMethodBar1() 또는 anotherMethodBar2()를 가지며, 이들은 인터페이스의 일부가 아닙니다.) 질문은 - 어떻게해야합니까? 나는 C#에 익숙하지 않고 지금까지는 내 경험이 캐스팅과 관련이 없지만 지금은 필요로합니다. 이것은 심지어 캐스팅을 사용하여 완료 되었습니까? 아니면 다른 방법입니까? 단순히 C 번호는 아래에 놓여 정확한 유형을 이해하지 못하기 때문에

if(fooBarObjects[i].GetType() == typeof(bar1)) 
{ 
    fooBarObjects[i].anotherMethodBar1(); 
} 

이 때문에 사용할 수있는 방법은 /이 객체의 기능을 수있는 방법을 유일한 표준 한번 플러스 내()를 호출 할 수 없습니다 - 방법 :

  • A()
  • 같음()
  • GetType을()
  • GetHashCode()
  • ToString()

정말 해결책을 찾으려고했지만 지금까지는 인터페이스 변환 목록에 객체 목록이 꽤 자주 요청되었습니다.

감사합니다.

+0

했다에 요소 캐스트 무엇을 따기 bar1을 사용하고 anotherMethodBar1 "을 사용하십시오. –

+0

[CLR의 'as'키워드를 사용하여 비교 분석] (http://stackoverflow.com/a/)에서이 답변을 읽어 보시기 바랍니다. 496167/1730086). –

+0

고마워, 얘들 아! 정말 빠르고 도움이됩니다. Knaģis가 가장 좋은 답변 인 omho입니다. "is"및 "as"키워드는 솔루션의 핵심 요소입니다. Mehmet Ataş가 제안한 것처럼 여러 번 캐스팅을 시도했지만 결과는 내 질문 끝에 설명되어 있습니다. 왜 그런 일이 일어 났는지 나는 정말로 이해하지 못했기 때문에 이것은 나를 귀찮게했다. "is"를 사용하면 문제가 해결되고 매력처럼 작동합니다. – rbaleksandar

답변

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

키는 개체 유형 bar1 (또는 bar1로부터 유도 된 임의의 유형) 및 개체를 지정된 형식으로 캐스트 (type)object 문법인지 검사 키워드 is이다.

캐스팅을 수행하는 키워드가 as이고 캐스팅을 수행 할 수없는 경우 null을 반환하는 옵션이 있습니다.

 for(int i = 0; i < fooBarObjects.Count; i++) 
     { 
      var b1 = fooBarObjects[i] as bar1; 
      if (b1 != null) 
      { 
       b1.anotherMethodBar1(); 
      } 
      else 
      { 
       var b2 = fooBarObjects[i] as bar2; 
       if (b2 != null) 
       { 
        b2.anotherMethodBar2(); 
       } 
      } 
     } 

는 두 번째 옵션은 런타임에만 두 번 (is())합니다 (as 키워드에) 한 번 확인 유형을 대신하기 때문에 처음에 걸쳐 권장 것으로 간주됩니다.

+1

이 경우에는'as'를 사용하고 결과를 null과 비교하여 사용할 수 있는지 확인하는 것이 좋습니다. 당신은'is'를 사용하고 타입을 두 번 검사 할 casting을합니다; 'as '를 사용하면 한 번만 유형을 검사합니다. –

+1

다형성을 사용하고 테스트를 전혀하지 않는 것이 좋습니다. – spender

+0

Matthew Watson, 훌륭한 팁. spender, 그렇습니다. 다형성을 사용하는 것도 가능하지만 제 (진짜) 경우 인터페이스를 사용하는 것이 더 쉽습니다. – rbaleksandar

1

당신은 as operator가하는 유형으로 시도 캐스트 사용할 수 있습니다

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

이 행사할 수있는 가장 읽기 쉽고 덜 오류가 발생하기 쉬운 방법입니다.

1

당신은 특정 유형의 항목을 추출 할 .OfType 확장 방법을 사용할 수 있습니다 : 물론

var allTheBar1s = fooBarObjects.OfType<bar1>(); 
foreach(bar1 item in allTheBar1s) 
{ 
    //bar1 action 
} 
//...etc... 

이이 bar2 항목에 대한 두 번째 반복을 필요로하지만,이 핫스팟이없는 한,이 정말하지 않습니다를 문제.

아마도 다형성과 단일 인터페이스 방법을 사용하여 작업을 적용하는 것이 좋습니다. 이렇게하면 테스트 유형에 대한 모든 종류의 요구 사항을 피할 수 있습니다.

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

단순히 캐스트 :

(fooBarObjects[i] as bar1).anotherMethodBar1(); 

당신이 "사실 당신이 당신의 의견에 답을 준

for(int i = 0; i < fooBarObjects.Count; i++) 
{ 
    if(fooBarObjects[i].GetType() == typeof(bar1)) 
     (fooBarObjects[i] as bar1).anotherMethodBar1(); 
} 
+0

Bang. 항목이 'bar1'이 아닌 경우 NullReferenceException – spender

+0

@ user2285800 : null을 확인하는 것을 잊지 마세요. –