2013-06-27 3 views
1

인벤토리 프로그램에서 클래스 ItemItemCollection과 파생 클래스 Computer : Item을 만들었습니다. 형태 C# 상속 - 기본 개체에서 파생 개체 구분

는, 나는 ItemCollection ( Item s의 일반적인 목록)를 생성 (일부 컴퓨터 포함) TheseItems라고 나는 (위치, 수량, 등 등) 각 항목 ThisItem의 속성을 표시합니다.

이 작업을 수행하는 동안 컴퓨터 (예 : CPU, HDD 및 RAM)의 고유 한 속성도 표시하려고합니다. 나는 이것을 지금까지 가지고있다 :

foreach (Item ThisItem in TheseItems) 
{ 
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading) 

    if (ThisItem is Computer) 
    { 
     //Display distinct properties of Computer instance “ThisItem” 
    } 
} 

지금까지 오류는 없지만 진행 방법은 확실하지 않다. 내가 원하는 것을 할 수 있습니까?

편집 : 감사, 스테이크! 캐스팅을하면 미리 할당 된 속성에 액세스 할 수 없으며 (단지 새 속성을 할당 할 수 있음) 걱정 스럽지만 운좋게 착각했습니다! 나는 지금 :

Computer ThisComputer = ThisItem as Computer; 
if (Computer != null) 
{ 
    //Display distinct properties of Computer instance “ThisComputer” 
} 

내가받은 빠른 도움에 정말 감탄했습니다. 감사!

+0

당신이 가지고있는 것은 일할 것입니다. –

답변

1

당신이 가지고있는 것.

foreach (Item ThisItem in TheseItems) 
{ 
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading) 
    var computerItem = ThisItem as Computer; 
    if (computerItem != null) 
    { 
     //Display distinct properties of Computer instance “ThisItem” 
    } 
} 

또한, 내 친구가이 도와주는 좋은 유틸리티 클래스를 썼습니다 :

foreach (Item ThisItem in TheseItems) 
{ 
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading) 

    if (ThisItem is Computer) 
    { 
     Computer computerItem = (Computer)ThisItem; 
     //Display distinct properties of Computer instance “ThisItem” 
    } 
} 

또는 약간의 최적화를위한 as 키워드를 사용합니다. 나는 그것이 매우 유용한 것으로 밝혀 졌기 때문에 나는 그것을 게시 할 것이라고 생각했다.

foreach (Item ThisItem in TheseItems) 
{ 
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading) 
    ThisItem.Match() 
      .Case<Computer>(comp => /* Do stuff with your computer */) 
      .Case<Television>(tv => /* Do stuff with your television */) 
      .Default(item => /* Do stuff with your item */); 
} 

유틸리티 클래스는 다음과 유사합니다. 아래는 요지를 제공하며 매우 확장 가능합니다.

public class Matcher<TMatch> 
{ 
    private readonly TMatch _matchObj; 
    private bool _isMatched; 

    public Matcher(TMatch matchObj) 
    { 
     this._matchObj = matchObj; 
    } 

    public Matcher<TMatch> Case<TCase>(Action<TCase> action) where TCase : TMatch 
    { 
     if(this._matchObj is TCase) 
     { 
      this.DoCase(() => action((TCase)this._matchObj)); 
     } 
     return this; 
    } 

    public void Default(Action<TMatch> action) 
    { 
     this.DoCase(() => action(this._matchObj)); 
    } 

    private void DoCase(Action action) 
    { 
     if (!this._isMatched) 
     { 
      action(); 
      this._isMatched = true; 
     } 
    } 
} 

public static class MatcherExtensions 
{ 
    public static Matcher<TMatch> Match<TMatch>(this TMatch matchObj) 
    { 
     return new Matcher<TMatch>(matchObj); 
    } 
} 
+0

그냥 나를 이길 수 있습니다. 내 대답은 DITTO입니다. –

+2

같은 일을하는 관용적 인 방법은'Computer computerItem = ThisItem as Computer; if (computerItem! = null) {...}'. 'is' 연산자는 실제로'as '연산을 수행 한 다음'null'을 검사하기 때문에'is'를 수행 한 다음 캐스트가 실제로 추가 명령을 필요로합니다. – dlev

0

예, 파생 된 클래스로 캐스트하면 속성을 사용할 수 있습니다.

foreach (Item ThisItem in TheseItems) 
{ 
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading) 

    if (ThisItem is Computer) 
    { 
     var ThisComputer = (Computer) ThisItem; 
     Display(ThisComputer.CPU); 
     //etc 
    } 
} 
1

이것은 일반적으로 사용하는 방법입니다. 유형을 확인한 다음 캐스팅하는 것보다 약간 빠를 수도 있습니다 (이 사실을 증명할 수 없습니다).

foreach (Item ThisItem in TheseItems) 
{ 
    //Display properties of Item instance “ThisItem” (Excluded for ease of reading) 

    var computer = ThisItem as Computer; 
    if (computer != null) 
    { 
     //Display distinct properties of Computer instance “ThisItem” 
    } 
} 
1

알려주지 마십시오.

는 배타적 속성을 포함 Computer 그것을 당신이 그들을 쓸 수 있도록, 그런 다음

foreach (Item ThisItem in TheseItems) 
{ 
    ThisItem.DisplayProperties(Console.out); 
} 

그들을 작성을 말해, 해당 속성에 대한 ThisItem에게 DisplayProperties() 가상 만들고, 너무 많이 넣지 마십시오 .

+0

+1이 유형의 문제에 대해 가장 좋은 답변 인 경우가 있지만 항상 그런 것은 아닙니다. 그것은 아마도 OP에 대한 최상의 대답 일 것입니다. –