Есть ли способ сделать динамическое неявное литье типов в С#?

Учитывая этот класс с неявным оператором литья:

public class MyDateTime
{
    public static implicit operator MyDateTime(System.Int64 encoded)
    {
        return new MyDateTime(encoded);
    }

    public MyDateTime(System.Int64 encoded)
    {
        _encoded = encoded;
    }
    System.Int64 _encoded;
}

Теперь я могу сделать следующее:

long a = 5;
MyDateTime b = a;

Но НЕ следующее:

long f = 5;
object g = f;
MyDateTime h = g;

Это дает время компиляции:

Невозможно неявно преобразовать тип 'object' в 'MyDateTime'.

Имеет смысл для меня.

Теперь я изменяю предыдущий пример следующим образом:

long f = 5;
object g = f;
MyDateTime h = (MyDateTime)g;

Это компилируется отлично. Теперь я получаю время выполнения InvalidCastException:

Невозможно передать объект типа 'System.Int64' для ввода MyDateTime '.

Это говорит мне, что С# неявные операторы литья применяются только во время компиляции и не применяются, когда среда выполнения .NET пытается динамически передать объект другому типу.

Мои вопросы:

  • Правильно ли я?
  • Есть ли другой способ сделать это?

Кстати, полное приложение состоит в том, что я использую Delegate.DynamicInvoke() для вызова функции, которая принимает параметр MyDateTime, а тип аргумента, который я передаю в DynamicInvoke, длинный.

Ответ 1

Правильно ли я?

Да, да. Чтобы быть ничтожным, вы должны сказать "пользовательское неявное преобразование", а не "неявное приведение" - приведение (почти) всегда явное. Но ваш вывод о том, что разрешение перегрузки выбирает, какое пользовательское преобразование для вызова во время компиляции, а не во время выполнения, является правильным.

Есть ли другой способ сделать это?

Да. В С# 4, если вы набираете свой "объект" как "динамический", мы снова запускаем компилятор во время выполнения и повторно выполняем весь анализ операндов, как если бы их типы времени компиляции были текущими типами времени выполнения. Как вы можете себе представить, это не дешево, хотя мы очень умны в кэшировании и повторном использовании результатов, если вы сделаете это в узком цикле.

Ответ 2

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

long f = 5;
object g = f;
MyDateTime h = g as MyDateTime;