416 Stimmen

Gibt es eine bessere Alternative zu diesem "Einschalttyp"?

Da C# nicht in der Lage ist switch bei einem Typ (der, wie ich annehme, nicht als Sonderfall hinzugefügt wurde, weil is Beziehungen bedeuten, dass mehr als eine bestimmte case gelten könnte), gibt es eine bessere Möglichkeit, das Einschalten des Typs zu simulieren als diese?

void Foo(object o)
{
    if (o is A)
    {
        ((A)o).Hop();
    }
    else if (o is B)
    {
        ((B)o).Skip();
    }
    else
    {
        throw new ArgumentException("Unexpected type: " + o.GetType());
    }
}

4voto

jgarcia Punkte 178

Eine andere Möglichkeit wäre, eine Schnittstelle IThing zu definieren und diese dann in beiden Klassen zu implementieren hier ist der Ausschnitt:

public interface IThing
{
    void Move();
}

public class ThingA : IThing
{
    public void Move()
    {
        Hop();
    }

    public void Hop(){  
        //Implementation of Hop 
    }

}

public class ThingA : IThing
{
    public void Move()
    {
        Skip();
    }

    public void Skip(){ 
        //Implementation of Skip    
    }

}

public class Foo
{
    static void Main(String[] args)
    {

    }

    private void Foo(IThing a)
    {
        a.Move();
    }
}

4voto

Jonas Kongslund Punkte 4810

Ich würde entweder

  • Methodenüberladung verwenden (genau wie x0n ), oder
  • Unterklassen verwenden (genau wie Pablo ), oder
  • den Besucherverhalten .

3voto

Chan Punkte 21

Wenn Sie die Klasse kennen, die Sie erwarten, aber noch kein Objekt haben, können Sie auch dies tun:

private string GetAcceptButtonText<T>() where T : BaseClass, new()
{
    switch (new T())
    {
        case BaseClassReview _: return "Review";
        case BaseClassValidate _: return "Validate";
        case BaseClassAcknowledge _: return "Acknowledge";
        default: return "Accept";
    }
}

3voto

Sergey Berezovskiy Punkte 223446

Sie können überladene Methoden erstellen:

void Foo(A a) 
{ 
    a.Hop(); 
}

void Foo(B b) 
{ 
    b.Skip(); 
}

void Foo(object o) 
{ 
    throw new ArgumentException("Unexpected type: " + o.GetType()); 
}

Und werfen Sie das Argument auf dynamic Typ, um die statische Typenprüfung zu umgehen:

Foo((dynamic)something);

2voto

mcintyre321 Punkte 12488

Sie suchen nach Discriminated Unions die ein Sprachmerkmal von F# sind, aber Sie können einen ähnlichen Effekt erzielen, indem Sie eine von mir entwickelte Bibliothek namens OneOf

https://github.com/mcintyre321/OneOf

Der größte Vorteil gegenüber switch (und if y exceptions as control flow ) ist, dass es kompilierungssicher ist - es gibt keinen Standard-Handler oder Fall-Through

void Foo(OneOf<A, B> o)
{
    o.Switch(
        a => a.Hop(),
        b => b.Skip()
    );
}

Wenn Sie ein drittes Element zu o hinzufügen, erhalten Sie einen Compilerfehler, da Sie einen Handler Func innerhalb des Switch-Aufrufs hinzufügen müssen.

Sie können auch eine .Match die einen Wert zurückgibt, anstatt eine Anweisung auszuführen:

double Area(OneOf<Square, Circle> o)
{
    return o.Match(
        square => square.Length * square.Length,
        circle => Math.PI * circle.Radius * circle.Radius
    );
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X