C#-schakelaar type [duplicate]

Mogelijk duplicaat:
C# – Is er een betere alternatief dan dit om ‘type in te schakelen’?

C# ondersteunt het inschakelen van het type object niet.
Wat is het beste patroon om dit te simuleren:

switch (typeof(MyObj))
    case Type1:
    case Type2:
    case Type3:

Antwoord 1, autoriteit 100%

Zie het antwoord van gjvdkamp; deze functie bestaat nu in C#


Ik gebruik meestal een woordenboek met typen en afgevaardigden.

var @switch = new Dictionary<Type, Action> {
    { typeof(Type1), () => ... },
    { typeof(Type2), () => ... },
    { typeof(Type3), () => ... },
};
@switch[typeof(MyType)]();

Het is iets minder flexibel omdat je niet door zaken kunt vallen, door kunt gaan enz. Maar ik doe dat toch zelden.


Antwoord 2, autoriteit 92%

Bijwerken:
Dit is opgelost in C# 7.0 met patroonovereenkomst

switch (MyObj)
    case Type1 t1: 
    case Type2 t2:
    case Type3 t3:

Oud antwoord:

Het is een gat in het spel van C#, nog geen wondermiddel.

Je zou moeten googlen op het ‘bezoekerspatroon’, maar het is misschien een beetje zwaar voor je, maar toch iets dat je zou moeten weten.

Hier is nog een andere kijk op de kwestie met Linq: http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx

Anders zou iets in deze richting kunnen helpen

// nasty..
switch(MyObj.GetType().ToString()){
  case "Type1": etc
}
// clumsy...
if myObj  is Type1 then
if myObj is Type2 then

enz.


Antwoord 3, autoriteit 13%

Er is een eenvoudig antwoord op deze vraagdat gebruikmaakt van een woordenboek van typen om een ​​lambda-functie op te zoeken. Hier is hoe het kan worden gebruikt:

var ts = new TypeSwitch()
    .Case((int x) => Console.WriteLine("int"))
    .Case((bool x) => Console.WriteLine("bool"))
    .Case((string x) => Console.WriteLine("string"));
ts.Switch(42);
ts.Switch(false);
ts.Switch("hello");

Er is ook een algemene oplossing voor dit probleemin termen van patroon matching (zowel typen als runtime gecontroleerde voorwaarden):

var getRentPrice = new PatternMatcher<int>()
    .Case<MotorCycle>(bike => 100 + bike.Cylinders * 10) 
    .Case<Bicycle>(30) 
    .Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
    .Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
    .Default(0);
var vehicles = new object[] {
    new Car { EngineType = EngineType.Diesel, Doors = 2 },
    new Car { EngineType = EngineType.Diesel, Doors = 4 },
    new Car { EngineType = EngineType.Gasoline, Doors = 3 },
    new Car { EngineType = EngineType.Gasoline, Doors = 5 },
    new Bicycle(),
    new MotorCycle { Cylinders = 2 },
    new MotorCycle { Cylinders = 3 },
};
foreach (var v in vehicles)
{
    Console.WriteLine("Vehicle of type {0} costs {1} to rent", v.GetType(), getRentPrice.Match(v));
}

Antwoord 4

Ik heb het een keer gedaan met een tijdelijke oplossing, ik hoop dat het helpt.

string fullName = typeof(MyObj).FullName;
switch (fullName)
{
    case "fullName1":
    case "fullName2":
    case "fullName3":
}

Antwoord 5

Ik heb deze vorm van switch-casezelden gebruikt. Zelfs toen heb ik een andere manier gevonden om te doen wat ik wilde. Als je merkt dat dit de enige manier is om te bereiken wat je nodig hebt, raad ik de oplossing van @Mark H aan.

Als dit bedoeld is als een soort besluitvormingsproces voor het maken van een fabriek, zijn er betere manieren om het te doen. Anders zie ik echt niet in waarom je de schakelaar op een type wilt gebruiken.

Hier is een klein voorbeeld dat de oplossing van Mark uitbreidt. Ik denk dat het een geweldige manier is om met typen te werken:

Dictionary<Type, Action> typeTests;
public ClassCtor()
{
    typeTests = new Dictionary<Type, Action> ();
    typeTests[typeof(int)] = () => DoIntegerStuff();
    typeTests[typeof(string)] = () => DoStringStuff();
    typeTests[typeof(bool)] = () => DoBooleanStuff();
}
private void DoBooleanStuff()
{
   //do stuff
}
private void DoStringStuff()
{
    //do stuff
}
private void DoIntegerStuff()
{
    //do stuff
}
public Action CheckTypeAction(Type TypeToTest)
{
    if (typeTests.Keys.Contains(TypeToTest))
        return typeTests[TypeToTest];
    return null; // or some other Action delegate
}

Other episodes