Почему оператор "as" не использует оператор неявного преобразования в С#?

Я определил неявное преобразование строк из/в определенный тип в С# (фиктивный код):

public class MyType
{
    public string Value { get; set; }

    public static implicit operator MyType(string fromString)
    {
        return new MyType { Value = fromString };
    }

    public static implicit operator string(MyType myType)
    {
        return myType.Value;
    }
}

Где-то во внешнем библиотечном коде экземпляр MyType передается методу в качестве параметра object. Часть этого метода выглядит примерно так:

private void Foo(object value)
{
    // ... code omitted
    var bar = value as string // note that value is an instance of MyType at runtime
    if(bar != null) // false, cast fails
    {
       // ... code omitted
    }
}

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

Будет ли это работать, если вместо MyType был конвертер explicit? Если да, (как) я могу иметь оба?

Кстати, бросок определенно работает, если тип известен в время компиляции. Это потому, что операторы static? Есть ли что-то вроде операторов нестатического преобразования?

P.S. Меня больше всего интересуют различия между поведением во время компиляции и временем выполнения, поэтому у меня есть следующий вопрос: Почему неявные операторы преобразования типов не динамически используются во время выполнения в С#?

Ответ 1

Почему мягкий актер не использует неявный конвертер?

Хорошо, что язык указан, в основном. Из раздела спецификации С# 5 7.10.11:

Если тип времени компиляции E не является динамическим, операция E как T дает тот же результат, что и

E is T ? (T)(E) : (T)null

за исключением того, что E оценивается только один раз.

[...]

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

Ответ 2

Спецификация языка С# явно упоминает это в документации для as:

Обратите внимание, что некоторые преобразования, такие как пользовательские преобразования, не являются возможно с оператором as и вместо этого выполняется литые выражения.

Итак, вы должны бросить его.

Ответ 3

as ключевое слово не учитывает определяемые пользователем операторы. Вместо этого вам нужно использовать оператор трансляции. Связанная статья из eric lippert

В вашем случае как явные, так и неявные операторы не могут помочь вам, поскольку вы пытаетесь использовать от object до string не от MyType до string. Чтобы пользовательские операторы преобразования работали, скомпилируйте тип времени экземпляра типа MyType вместо object. Поскольку преобразование существует от object до string, но от MyType до string.

Ответ 4

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

var castObj = rawObj как SomeType;

потребовалось бы, чтобы среда выполнения .NET использовала отражение, чтобы определить, имеет ли объект "rawObj" оператор преобразования. Очевидно, что это было бы намного более дорогостоящим вычислительным, чем просто проверить, является ли объект типом SomeType или его подтипом. Лучше иметь быстрый и предсказуемый оператор, чем более универсальный, но гораздо более медленный.