Могу ли я вернуть произвольное значение для определенного типа в универсальном методе?

#c# #generics

#c# #универсальные

Вопрос:

Я хочу определить универсальный метод, который возвращает 42, если предоставленный аргумент является int, в противном случае возвращает аргумент без изменений.

Наивная реализация не компилируется:

 // Compilation fails with: "Cannot implicitly convert type `int' to `T'"
public static T Id42<T>(T x) {
    if(x is int) {
        return 42;
    }
    return x;
}
  

Приведение к объекту first работает, но завершается ошибкой во время выполнения, если типы не совпадают:

 // If I replace 42 with a string it compiles successfully and crashes at runtime
public static T Id42<T>(T x) {
    if(x is int) {
        return (T)(Object)42;
    }
    return x;
}
  

Кажется, что мой лучший вариант — вернуть Object вместо T .

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

Комментарии:

1. Какую ошибку вы получаете? Выполняется для меня: dotnetfiddle.net/5VuYIs

2. Я не уверен, что понимаю, от чего вы пытаетесь защититься. Проверка того, T есть int ли это, а затем попытка привести что-либо, отличное от int to T , всегда приведет к сбою. Предложение @Nyerguds использовать отдельные перегрузки, возможно, безопаснее, поскольку тогда вы можете отказаться от изначально более рискованного понижения.

3. Во время компиляции на языке со статической типизацией вы будете знать, будет ли ваш результат с плавающей точкой или нет, и возврат с плавающей точкой, приведенной к T внутри условного выражения, которое установило, что это T есть int (конечно, это не точно то, что на самом деле тестирует ваше текущее условное выражение), выдаст результат. ETA: можете ли вы предоставить описание проблемы, которую это пытается решить? Мне все еще не ясно, какова цель, и, возможно, есть лучший способ приблизиться к ней.

4. @shambulator я вижу. Это имеет смысл.

5. @shambulator Моя цель — узнать, как универсальные методы работают на разных языках. То, что я пытаюсь здесь сделать, возможно в языках с разными системами типов (например, в Haskell вы бы использовали GADT для «доказательства» равенства типов). Я хочу посмотреть, какие возможности есть в более распространенном языке. Насколько я понимаю, ответ, похоже, заключается в том, что это невозможно таким образом, но тот же результат, вероятно, может быть достигнут путем перегрузки.