Ilan_Schindler
Ilan_Schindler

Reputation: 11

Switch Statement based on Class Properties

I understand this is a rather confusing and weird thing to need to do, but is there any way to have a switch statement work based on the properties of an object. Like passing in an object's property, not the value of the property but the property itself, and having a switch evaluate?

The main goal is to have an object with a bunch of different properties and each property has conditions for whether the overall object is true or false, so I want to be able to call a single method from multiple places and have each place say which property it wants to be checked for T/F.

ex:

public class Foo{
  public int StuffsLimit{get;set;}
  public List<int> SomeList {get;set;}
}
...
switch(x){
  case Foo.StuffsLimit:
    //here, we check whether THIS condition is true
    return numberOfStuffs < StuffsLimit;    
  case Foo.SomeList:
    //here, we check if a different condition is true
    return SomeList.Contains(5);
}

im doing this to try to minimize extra/redundant code. The same property may need to be checked in multiple spots, so I want to avoid putting the actual check in those spots, but I also want to avoid using an Enum or individual methods for everything so that this will work dynamically as new properties get added to the original object.

Thank you

Upvotes: 0

Views: 3633

Answers (2)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112324

It looks like you need some validation code. I would pass the validation method a Foo object together with the name of the property you want to validate.

public bool IsValid(Foo foo, string propertyName)
{
    switch(propertyName) {
        case nameof(Foo.StuffsLimit):
            return numberOfStuffs < foo.StuffsLimit;    
        case nameof(Foo.SomeList):
            return foo.SomeList.Contains(5);
        default:
            return false;
    }   
}

With the new C# 8.0 switch expression, and the expression bodied members you can simply it:

public bool IsValid(Foo foo, string propertyName) =>
    propertyName switch {
        nameof(Foo.StuffsLimit) => numberOfStuffs < foo.StuffsLimit,
        nameof(Foo.SomeList) => foo.SomeList.Contains(5),
        _ => false
    };

Note that nameof(Foo.StuffsLimit) is identical to "StuffsLimit". The first variant is checked by the compiler and is subject to rename refactorings, the second is not. Of course you can use nameof() when calling this method: if (!IsValid(foo, nameof(Foo.SomeList))) { ... }

Upvotes: 2

Polyfun
Polyfun

Reputation: 9639

This is an ideal case for some classic object-oriented polymorphism, which is another way of saying you want different behaviour for different types of object, when you don't know what type of object you have got, but you do know it inherits from a specific base class.

public class Foo
{
    public abstract bool Evaluate();
}

public class FooChildA : Foo
{
    public int StuffsLimit { get; set; }

    public override bool Evaluate()
    {
        return numberOfStuffs < StuffsLimit;
    }
}

public class FooChildB : Foo
{
    public List<int> SomeList { get; set; }

    public override bool Evaluate()
    {
        return SomeList.Contains(5);;
    }
}

// Somewhere later:

Foo foo = FooChildA();
// Calls FooChildA.Evaluate();
foo.Evaluate();
foo = FooChildB();
// Calls FooChildB.Evaluate();
foo.Evaluate();

Upvotes: 1

Related Questions