문제

현재이 코드에 새로운 확장 클래스를 추가하고 있습니다.

foreach (BaseType b in CollectionOfExtendedTypes) {
  if (b is ExtendedType1) {
    ((ExtendedType1) b).foo = this;

  }
  else if (b is ExtendedType2) {
    ((ExtenedType2) b).foo = this;

  } 
  else {
    b.foo = this;

  }
}

그리고 사용 방법이 있는지 궁금했습니다. is 스위치 문의 키워드 기능?

도움이 되었습니까?

해결책

이것은 정말 좋은 다형성 구현의 상황처럼 보입니다. 파생 클래스에서 적절한 방법을 무시하면 루프에서 확인이 필요하지 않을 수 있습니다.

다른 팁

C# (7)의 최신 버전에는 이제이 기능이 포함됩니다.

유형 패턴

유형 패턴은 간결한 유형 평가 및 변환을 가능하게합니다. 패턴 일치를 수행하기 위해 Switch 문과 함께 사용되면 표현식을 지정된 유형으로 변환 할 수 있는지 여부를 테스트하고 가능하다면 해당 유형의 변수로 캐스트합니다. 구문은 다음과 같습니다.

   case type varname 

C#에서는 "IS"키워드를 스위치 문의 일부로 사용할 수 없습니다. 스위치의 모든 케이스 레이블은 일정한 표현식으로 평가해야합니다. "is"는 일정한 표현으로 전환 할 수 없습니다.

유형을 켜는 데있어 고통을 확실히 느낍니다. 당신이 설명한 해결책은 실제로 작동하지만 x do y에 대해 말하는 방법입니다. b. 다음과 같이 글을 쓰는 것이 훨씬 더 나일 것입니다.


TypeSwitch.Do(
    sender,
    TypeSwitch.Case<Button>(() => textBox1.Text = "Hit a Button"),
    TypeSwitch.Case<CheckBox>(x => textBox1.Text = "Checkbox is " + x.Checked),
    TypeSwitch.Default(() => textBox1.Text = "Not sure what is hovered over"));

다음은이 기능을 달성하는 방법에 대해 쓴 블로그 게시물입니다.

http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx

확인 유형에 Switch 문을 사용할 수는 없지만 문제를보다 관리하기 쉬운 코드베이스로 줄이는 것은 불가능하지 않습니다.

특정 상황과 요구 사항에 따라 고려할 것입니다.

  • 사용 a IDictionary<Type, T> 결과를 사전에 저장합니다. t 자체는 당신이 전화 할 수있는 대의원 일 수 있습니다. 상속에 대해 걱정할 필요가 없다면 작동합니다. 상속을위한 케이터링에는 조금 더 많은 작업이 필요합니다.

  • 스위치 문 내에서 클래스의 유형 이름 (문자열)을 사용합니다. 이것은 사용합니다 switch (b.GetType().Name) 그리고 깊은 상속 구조에 대한 옵션은 없습니다.

에 언급했듯이 대답 ~에서 미킷, 당신은 사용할 수 있습니다 패턴 수학 C# 7이 필요합니다.

코드의 예는 다음과 같습니다.

foreach (BaseType b in CollectionOfExtendedTypes) {
  switch (b) {
    case ExtendedType1 et1:
        // Do stuff with et1.
        et1.DoStuff();
        break;
    case ExtendedType2 et2:
        // Do stuff with et2.
        et2.DoOtherStuff();
        break;
    default:
        // Do something else...
        break;
  }
}

메소드를 추가 할 수 있습니다 getType() 에게 BaseType 이는 각 콘크리트 서브 클래스에서 구현하여 고유 한 적분 ID (열거)를 반환하고이를 켜십시오.

실제로 스위치는 변수 (String 또는 int (또는 Enum))과 일치하여 Switch 문으로 일정한 표현식과 일치합니다.

http://msdn.microsoft.com/en-us/library/06tc147t(vs.71).aspx

C#에서는 스위치 문이 정수 및 문자열과 만 작동한다고 생각합니다.

유형의 케이스와 객체 지향 코드는 내 경험에 따라 그와 잘 어울리지 않는 것 같습니다. 이 상황에서 내가 선호하는 접근법은 다음과 같습니다 이중 디스패치 패턴. 요컨대 :

  • 리스너 유형을 만듭니다 각 확장 된 유형에 대해 빈 가상 메소드 프로세스 (ExtendedTypen Arg)를 사용하면 배출됩니다.
  • 가상 메소드를 추가하십시오 청취자를 인수로 취하는 기본 유형으로 디스패치 (리스너 리스너)를 디스패치하십시오. 구현은 Listener.process ((기본) this)를 호출하는 것입니다.
  • 위에타다 적절한 것을 호출하기 위해 각 확장 유형의 디스패치 방법 ~ 위에 청취자 유형의 프로세스.
  • 리스너 유형을 확장합니다 관심있는 각 하위 유형에 대한 적절한 프로세스 방법을 재정의함으로써.

인수 셔플 링 댄스는 파견 호출로 접어 좁아진 캐스트를 제거합니다. 수신기는 정확한 유형을 알고 있으며 그 유형의 정확한 과부하를 다시 호출하여 통신합니다. 이는 또한 .NET Compact 프레임 워크와 같은 구현에서 큰 성능을 얻는 것입니다. 여기서 좁은 캐스트는 매우 느리지 만 가상 파견이 빠릅니다.

결과는 다음과 같습니다.


public class Listener
{
    public virtual void Process(Base obj) { }
    public virtual void Process(Derived obj) { }
    public virtual void Process(OtherDerived obj) { }
}

public class Base
{
    public virtual void Dispatch(Listener l) { l.Process(this); }
}

public class Derived
{
    public override void Dispatch(Listener l) { l.Process(this); }
}

public class OtherDerived
{
    public override void Dispatch(Listener l) { l.Process(this); }
}

public class ExampleListener
{
    public override void Process(Derived obj)
    {
        Console.WriteLine("I got a Derived");
    }

    public override void Process(OtherDerived obj)
    {
        Console.WriteLine("I got an OtherDerived");
    }

    public void ProcessCollection(IEnumerable collection)
    {
        foreach (Base obj in collection) obj.Dispatch(this);
    }
}

컴파일러가 처리하는 방식 외에 다른 생각이 있습니다. switch 진술, 그리고 그것이 기능입니다 is 운영자. 다음 사이에는 큰 차이가 있습니다.

if (obj is Foo)

그리고

if (obj.GetType() == typeof(Foo))

이름에도 불구하고 is 운영자는 객체가 있는지 알려줍니다 호환 가능 주어진 유형의 경우 ~이다 주어진 유형의. 이것은 단호한 버그로 이어집니다 (이것은 분명하지만).

if (obj is System.Object)
{
   //this will always execute
}
else if (obj is Foo)
{
   //this will never execute
}

여기에서 많은 제안이 객체 유형을 사용하는 방향을 지적합니다. 당신이 정말로 원하는 것이 각 유형과 관련된 논리라면 괜찮습니다. 그러나 그런 경우라면, 사용할 때 조심스럽게 걷습니다. is 운영자.

또한 : 이러한 기본 유형을 수정할 수는 없지만 Owen의 제안을 사용할 수 없다는 의미는 아닙니다. 확장 방법을 구현할 수 있습니다.

public enum MyType { Foo, Bar, Baz };
public static class MyTypeExtension
{
   public static MyType GetMyType(this Foo o)
   {
      return MyType.Foo;
   }
   public static MyType GetMyType(this Bar o)
   {
      return MyType.Bar;
   }
   public static MyType GetMyType(this Baz o)
   {
      return MyType.Baz;
   }
}

그럼 당신 ~할 수 있다 a switch 성명:

switch (myObject.GetType())
{
   case MyType.Foo:
     // etc.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top