Скрыть неявные операторы на основе условия? - PullRequest
0 голосов
/ 05 декабря 2018

Вероятно, глупый вопрос, потому что ответ, скорее всего, будет нет;но так как я не могу найти документированный ответ в Интернете, я спрошу здесь.У меня есть класс, который имеет шесть implicit методов преобразования.Причиной этого является упрощение динамической логики в другом месте моего приложения.

// Just an example for simplicity.
public class Number {
    private object val;

    public Number(int i) { val = i; }
    public Number(long l) { val = l; }
    public Number(double d) { val = d; }

    public static implicit operator int(Number n) => (int)n.val;
    public static implicit operator long(Number n) => (long)n.val;
    public static implicit operator double(Number n) => (double)n.val;
}

Мне интересно, есть ли способ скрыть преобразования (как в случае с ошибкой компилятора или аналогичные), которые не будут работать на основена чем создается экземпляр класса Number в моем примере?Если нет способа скрыть это, есть ли способ гарантировать, что всегда используется правильное неявное преобразование?

Я полагаю, что безопасный путь - это просто сделать свойство val public с именемValue и просто вернуть объект и вместо этого сделать явные преобразования.Кроме того, как примечание, я не делаю это с основными типами;Я пытаюсь инкапсулировать группу пользовательских типов, которые похожи, но не имеют общего базового класса, к моему несчастью.

1 Ответ

0 голосов
/ 05 декабря 2018

Фактически, цель выраженного вами класса Number состоит в том, чтобы обойти компилятор и разрешить неявное приведение, которое может быть недопустимым.Вы говорите компилятору , а не , чтобы проверить тип, и вместо этого разрешаете исключение времени выполнения, если приведение не допустимо.

Попытка заставить компилятор выдать предупреждение означает, что попытка заставить его делать именно то, что вы сказали, не делать.

В некотором смысле это ничем не отличается от использования object вместо Number.

Если вы решите использовать object, то компилятор вам не поможет.Вы отказываетесь от безопасности типов, а это значит, что вы должны каким-то образом убедиться, что вы отслеживаете, откуда берется каждое значение, и во что оно может или не может быть преобразовано, чтобы вы не получили ошибок времени выполнения.

Безопасность типов - это просто безопасность.Это защитные ограждения, которые помогают нам не писать код, который потерпит неудачу при запуске.Я рекомендую всегда использовать его, если нет действительно важной причины не делать этого, как правило, когда конкретный тип не имеет значения.Обычно это так.

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

С другой стороны, предположим, что есть общность.Скажем, например, у каждого из ваших базовых типов есть свойство, которое возвращает строку, но это свойство отличается для каждого типа.В этом случае вы можете создать интерфейс, например:

public interface IHasMyStringProperty
{
    string GetTheString { get; }
}

Затем создайте оболочку для разных классов, примерно так:

public class Foo
{
    public string FooString { get; }
}

public class FooWrapper : IHasMyStringProperty
{
    private readonly Foo _foo;

    public FooWrapper(Foo foo)
    {
        _foo = foo;
    }

    public string GetTheString => _foo.FooString;
}

Обратите внимание, что мы необновление класса Foo для реализации интерфейса, хотя это тоже может быть вариантом.Вместо этого мы создаем общий интерфейс и создаем оболочки (или адаптеры) для адаптации различных типов к этому общему интерфейсу.(У вас могут быть оба - классы, которые реализуют интерфейс, и классы, которые нуждаются в обертках.) В результате получается безопасность типов.Мы пишем все остальные наши методы для работы только с IHasMyStringProperty.Если мы хотим передать какой-то другой тип, нам просто нужно определить оболочку, которая реализует этот интерфейс.

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