Общий перегруженный метод с обнуляемым параметром, вызывающим конкретный тип - PullRequest
2 голосов
/ 07 февраля 2012

Я хочу иметь возможность вызывать универсальный метод foo с параметром Nullable.Когда тело метода Foo вызывает Foo (), оно становится рекурсивным, что приводит к переполнению стека (без .com).Есть ли способ, чтобы вызов в операторе if вызывал корректную перегрузку с типом среды выполнения?

Я знаю, что изменение имен сделает это, и я понимаю, почему происходит рекурсия, но не знаюЕще один способ написать это.

Спасибо за поиск.

class Program {
    static void Main(string[] args) {
        int? x = 5;
        int y = 10;
        Foo(x, y);
    }

    static void Foo<T>(Nullable<T> arg, T defaultValue) where T : struct {
        if (arg.HasValue)
            Foo(arg.Value, defaultValue);
    }

    static void Foo(int arg, int defaultValue) {
        Console.WriteLine(string.Format("I'm an int arg={0}, default={1]}", arg, defaultValue));
    }

    static void Foo(string arg, int defaultValue) {
        Console.WriteLine(string.Format("I'm an string arg={0}, default={1]}", arg, defaultValue));
    }

    static void Foo(bool arg, int defaultValue) {
        Console.WriteLine(string.Format("I'm an double arg={0}, default={1]}", arg, defaultValue));
    }
}

1 Ответ

1 голос
/ 07 февраля 2012

Обобщения являются функцией времени компиляции, разрешение перегрузки было решено еще до запуска программы. Если вы хотите, как вы говорите, принудительно принять решение во время выполнения, вы можете использовать dynamic для достижения этой цели (в C # 4+). Если не считать этого, вы просто должны привести к соответствующему типу между int и bool в противном случае.

  if (arg.HasValue) 
        Foo((dynamic)arg.Value, defaultValue); 

Но будьте осторожны! Это решит вашу проблему только для int и bool. Другие типы могут быть переданы универсальному методу, и они будут продолжать преобразовываться в универсальный метод при последующем вызове.

 Foo(5.0, 10.0); // would still overflow with your given methods

Следуйте вашему первоначальному суждению, если вы хотите поддерживать int, string и bool, просто имейте эти перегрузки. Если вы хотите поддерживать любой данный T, создайте перегрузку для T.

static void Foo<T>(T arg, T defaultValue)
{
    Console.WriteLine(string.Format("I'm a T arg={0}, default={1}", arg, defaultValue));
}

Разрешение перегрузки будет по-прежнему выбирать перегрузки int, bool, string или T?, если они применимы на основе информации времени компиляции . Все остальные вызовы, и вызов с arg.Value, перейдут к этой новой перегрузке.

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