C # Явные операторы и наследование - PullRequest
9 голосов
/ 06 июня 2011

Я уверен, что это глупый вопрос, но почему следующий код не вызывает явный оператор для приведения дочернего класса MyBool?

public class DataType
{
    public static explicit operator bool(DataType D)
    {
        return false;
    }

    public static explicit operator DataType(bool B)
    {
        return new DataType();
    }
}

public class MyBool : DataType
{
    public bool Value;

    public MyBool()
    {
        Value = false;
    }

    public static explicit operator bool(MyBool B)
    {
        return B.Value;
    }

    public static explicit operator MyBool(bool B)
    {
        return new MyBool() { Value = B };
    }
}

затем:

List<DataType> Types = new List<DataType>();

Types.Add(new MyBool() { Value = true });
Types.Add(new MyBool() { Value = false });

foreach (DataType T in Types)
{
    bool Value = (bool)T;
    MessageBox.Show(Value.ToString());
}

Выводит вывод: false, false

Является ли моя единственная возможность писать функции в каждом классе, чтобы заменить явные операторные функции?

Ответы [ 3 ]

16 голосов
/ 06 июня 2011

почему следующий код не вызывает явный оператор для приведения дочернего класса MyBool?

Поскольку функции оператора static, следовательно, также не virtualи, следовательно, их цель решается в время компиляции , а не во время выполнения.Это ожидаемое поведение.

Если вы хотите иметь операторы полиморфного преобразования, вы можете вызывать виртуальные функции внутри , операторы:

public abstract class DataType
{
    public static explicit operator bool(DataType D)
    {
        return D.DoCastToBool();
    }

    public static explicit operator DataType(bool B)
    {
        // We haven’t got an instance of our class here.
        // You can use a factory method pattern to emulate virtual constructors.
    }

    protected abstract bool DoCastToBool();
}
2 голосов
/ 06 июня 2011

Операторы перегружены , а не переопределены - другими словами, выбор используемой реализации делается во время времени компиляции . Компилятору известно только о T как DataType, поэтому он вызывает оператор в DataType.

Один из вариантов - удалить оператор из MyBool, но добавить в DataType виртуальный метод, допускающий полиморфное поведение:

public class DataType
{
    public static explicit operator bool(DataType D)
    {
        // TODO: Decide how you want to handle null references
        return D.ToBoolean();
    }

    protected virtual bool ToBoolean()
    {
        return false;
    }
}

public class MyBool : DataType
{
    // ...

    protected override bool ToBoolean()
    {
        return Value;
    }
}

Обратите внимание, что этот не будет работать для преобразования из bool в DataType, так как в этом случае у нас нет никакой информации о том, какой подтип DataType вы действительно хотите создать.

(Примечание: ваш код будет легче следовать, если вы будете использовать обычные соглашения об именах .NET).

0 голосов
/ 22 октября 2018

Вот вам решение для мусора:

замените: bool Value = (bool)T;

на: bool Value = (bool)(T as MyBool);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...