Могу ли я установить ограничение C# generi c на "оператор true"? - PullRequest
1 голос
/ 13 марта 2020

Допустим, у меня есть класс, который содержит список логических значений, и я хочу свойство, которое сообщает, что все они 'true'. Есть несколько способов сделать это:

class BunchOfBools
{
    List<bool> Stuff = new List<bool>();
    bool AllAreTrue1 => Stuff.All(b => b);
    bool AllAreTrue2 => Stuff.TrueForAll(b => b);
}

Круто. Жизнь хороша.

Но теперь я понимаю, что у меня есть класс, который реализует «оператор истина» и «оператор ложь»

class BatteryIsGood
{
   float BatteryVoltage;

   public static bool operator true(BatteryIsGood ab) => ab.BatteryVoltage >= 3;
   public static bool operator false(BatteryIsGood ab) => ab.BatteryVoltage < 3;
}

И если у меня есть куча объектов BatteryIsGood ( да, это надуманный пример) и я хочу использовать BunchOfBools, чтобы проверить, все ли они хороши - поэтому сделайте BunchOfBools generi c:

class BunchOfBools<T>
{
    List<T> Stuff = new List<T>();
    bool AllAreTrue1 => Stuff.All(b => b);
    bool AllAreTrue2 => Stuff.TrueForAll(b => b);
    bool AllAreTrue3 => Stuff.All(b => (bool)b);
    bool AllAreTrue4 => Stuff.TrueForAll(b => (bool)b);
    bool AllAreTrue5
    {
        get
        {
            foreach (T one in Stuff)
            {
                if (!one)
                    return false;
            }
            return true;
        }
    }
    bool AllAreTrue6 => Stuff.All(b => (bool)(object)b);
    bool AllAreTrue7 => Stuff.TrueForAll(b => (bool)(object)b);
}

BunchOfBools<BatteryIsGood> allBatteriesAreGood;

Но, конечно, компилятор не совсем доволен generi c BunchOfBools (функции с 1 по 5 не компилируются), потому что "не может преобразовать тип 'T' в bool". AllAreTrue6 и AllAreTrue7 компилируются, но являются (1) некрасивыми, (2) неэффективными и (3) небезопасными (до времени выполнения вы не узнаете, что «T» не может преобразоваться в bool).

Is Есть ли способ добавить обобщенное ограничение c, которое говорит: «T должен реализовать оператор true»?

EDIT

Можно даже сказать, что класс должен реализовывать неявное преобразование в bool , если это поможет:

class BatteryIsGood
{
   float BatteryVoltage;

   public static bool operator true(BatteryIsGood ab) => (bool)ab;
   public static bool operator false(BatteryIsGood ab) => !((bool)ab);

   public static implicit operator bool(BatteryIsGood big) => ab.BatteryVoltage >= 3;
}

1 Ответ

0 голосов
/ 13 марта 2020

Вы можете использовать комбинацию ToString и Parse, как показано ниже:

class BunchOfBools<T>
{
    List<T> Stuff = new List<T>();
    bool AllAreTrue1 => Stuff.All(b => bool.Parse(b.ToString()));
    bool AllAreTrue2 => Stuff.TrueForAll(b => bool.Parse(b.ToString()));
    bool AllAreTrue3 => Stuff.All(b => (bool)bool.Parse(b.ToString()));
    bool AllAreTrue4 => Stuff.TrueForAll(b => (bool)bool.Parse(b.ToString()));
    bool AllAreTrue5
    {
        get
        {
            foreach (T one in Stuff)
            {
                if (!bool.Parse(one.ToString()))
                    return false;
            }
            return true;
        }
    }
    bool AllAreTrue6 => Stuff.All(b => (bool)(object)b);
    bool AllAreTrue7 => Stuff.TrueForAll(b => (bool)(object)b);
}
...