Оператор переключения на основе свойств класса - PullRequest
0 голосов
/ 17 июня 2020

Я понимаю, что это довольно запутанная и странная вещь, но есть ли способ заставить оператор switch работать на основе свойств объекта. Как передача свойства объекта, а не значения свойства, а самого свойства, и наличие переключателя для оценки?

Основная цель - получить объект с множеством разных свойств, и каждое свойство имеет условия для является ли общий объект истинным или ложным, поэтому я хочу иметь возможность вызывать один метод из нескольких мест и каждое место указывать, какое свойство он хочет проверять на 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);
}

Я делаю это, чтобы попытаться свести к минимуму лишний / избыточный код. Одно и то же свойство может потребоваться проверить в нескольких местах, поэтому я хочу избежать фактической проверки в этих местах, но я также хочу избегать использования Enum или отдельных методов для всего, чтобы это работало динамически по мере добавления новых свойств. к исходному объекту.

Спасибо

Ответы [ 2 ]

1 голос
/ 17 июня 2020

Похоже, вам нужен код проверки. Я бы передал методу проверки объект Foo вместе с именем свойства, которое вы хотите проверить.

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;
    }   
}

С новым выражением переключения C# 8.0 и членами выражения, содержащими тела, вы можете просто it:

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

Обратите внимание, что nameof(Foo.StuffsLimit) идентично "StuffsLimit". Первый вариант проверяется компилятором и подлежит рефакторингу переименования, второй - нет. Конечно, вы можете использовать nameof() при вызове этого метода: if (!IsValid(foo, nameof(Foo.SomeList))) { ... }

1 голос
/ 17 июня 2020

Это идеальный случай для некоторого классического c объектно-ориентированного полиморфизма, который является еще одним способом сказать, что вам нужно различное поведение для разных типов объектов, когда вы не знаете, какой тип объекта у вас есть, но вы знаете, что он наследуется от определенного c базового класса.

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...