Tuple.Create тип возвращаемого значения - PullRequest
2 голосов
/ 06 октября 2010

С учетом

void foo(Tuple<object> t)
{

}
void bar()
{
    foo(Tuple.Create("hello"));
}

компилятор c # возвращает

error CS1502: The best overloaded method match for 'foo(System.Tuple<object>)' has some invalid arguments
error CS1503: Argument 1: cannot convert from 'System.Tuple<string>' to 'System.Tuple<object>'

Добавление явных типов в Tuple. Создание побеждает его цель. Как я могу убедить компилятор принять код?

FWIW, я думаю, что C ++ не имеет этой проблемы: http://live.boost.org/doc/libs/1_33_1/libs/tuple/doc/tuple_users_guide.html#constructing_tuples

Ответы [ 3 ]

4 голосов
/ 06 октября 2010

Вы можете скомпилировать код с помощью не , используя Tuple<object>, но используя Tuple<T>

void foo<T>(Tuple<T> t)

Если вы не хотите этого делать, вы просто необходимо будет явно указать строку для объекта в методе Tuple.Create.

Tuple.Create<object>("Hello");
Tuple.Create((object)"Hello");

Подумайте, можете ли вы иметь Tuple<object>, а затем передать Tuple<string>.Что если ваша подпись была

void(ref Tuple<object> t)

Ничто не мешает вам писать в этом методе

t = new Tuple<object>(1);

И теперь вы просто поместили 1 в кортеж, который допускает только строки.Конечно, это угловой случай, поскольку Tuple изначально доступен только для чтения, поэтому вам нужен параметр ref, но, тем не менее, это проблемный случай.

4 голосов
/ 06 октября 2010

Это та же самая проблема ковариации универсального типа, которая возникает ежедневно. Просто невозможно конвертировать Foo<T> в Foo<SubT> или наоборот. Начиная с .NET 4, он поддерживается - но только для интерфейсов и делегатов, и путем явного указания параметра универсального типа в качестве варианта, объявив его Foo<out T1>.

2 голосов
/ 06 октября 2010

Вы пытаетесь превратить Tuple<string> в Tuple<object>, что вы не можете сделать - общая дисперсия поддерживается только для интерфейсов и делегатов. Вам необходимо явно указать аргументы типа для Tuple.Create:

void bar()
{
    foo(Tuple.Create<object>("hello"));
}
...