Вопрос по c#, dynamic, generics – Как можно использовать динамический как универсальный?

9

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

это

<code>var x = something not strongly typed;
callFunction<x>();
</code>

и это

<code>dynamic x = something not strongly typed;
callFunction<x>();
</code>

оба выдают эту ошибку

<code>Error   1   The type or namespace name 'x' 
could not be found (are you missing a using directive or an assembly reference?)
</code>

Что я могу сделать, чтобыx сделать его достаточно законным для использования в<x>?

var x не означает, что переменнаяx не сильно напечатан. Компилятор выводит (угадывает, если вы предпочитаете) тип выражения справа от= и делает это типомx, Если компилятор считает, что выражение имеет типstring затемvar x означает точно так же, какstring x, Обратите внимание, что это происходит во время компиляции, а не во время выполнения! Olivier Jacot-Descombes
@ M.Babcock - даже при преобразовании в тип выдается та же ошибка. Например:Type t; t = LegitimateObject.GetType(); callFunction<t>(); выдает ту же ошибку. Travis J
Ваш пример кода не имеет смысла: рассмотрите ваш код, если xwere строго напечатано:string x = "X";, Вы не звонитеCallFunction<x>() или жеCallFunction<typeof(string)>(); ты звонишьCallFunction<string>()  Это не имеет смысла, если только CallFunction не имеет строкового параметра или возвращаемого значения; Более вероятный звонок будетstring x = CallFunction<string>(); или жеCallFunction<string>(x), Можете ли вы привести пример функции, которую вы хотели бы вызвать? Чего ты пытаешься достичь? phoog
Нет не тип, как вSystem.Type тип как вstring или жеint непосредственно. Переменные нельзя использовать в качестве параметров типа. M.Babcock
Ваш код сбивает с толку. Похоже, вы пытаетесь передать переменную в качестве параметра типа? Это все равно не сработает. Это должен быть тип. M.Babcock

Ваш Ответ

6   ответов
15

Вы можете использовать вывод типа для батута вызова:

dynamic x = something not strongly typed;
CallFunctionWithInference(x);

...

static void CallFunctionWithInference<T>(T ignored)
{
    CallFunction<T>();
}

static void CallFunction<T>()
{
    // This is the method we really wanted to call
}

Это определит аргумент типа во время выполнения на основе типа времени выполнения значенияxиспользуя тот же тип вывода типа, который он использовал бы, еслиx было это как егоcompile-time тип. Параметрonly подарок, чтобы сделать вывод типа работы.

Обратите внимание, что в отличие от Дарина, я верю в этоis полезный метод - в тех же самых ситуациях, когда перед динамикой вы в конечном итоге вызываете универсальный метод с отражением. Вы можете сделать этоone часть кода динамическая, но сохранитьrest кода (от общего типа и далее) безопасного типа. Это позволяетone шаг, чтобы быть динамичным - только один бит, когда вы не знаете тип.

@TravisJ: Я думаю, что было бы полезно, если бы вы могли создать новый вопрос для этого, с коротким, ноcomplete Программа, демонстрирующая проблему.
@TravisJ: Очень любезно с вашей стороны - спасибо!
@TravisJ: Это потому чтоCallFunction само по себе имеет ограничение? Вы не сказали нам, что в вопросе :) Без ограничения наCallFunction это должно быть хорошо, хотя.
Да, извините за упущение :) Ограничение вCallFunction является инициализацией (вниз по линии) EF DbSet в видеthis.dbSet = context.Set<TEntity>(); который находится внутри общего репозитория, вызываемого из оператора using. В то время я не понимал, что это повлияет на результат, иначе я бы включил его. Travis J
Хах! Это работает, хорошо с небольшой адаптацией. Чистый гений. Я люблю это. Проблема в том, что с вашим текущим определением T должен быть ссылочным типом, чтобы использовать его в качестве параметра позже вCallFunction, Чтобы улучшить это, я сделал эти изменения:static void CallFunctionWithInference<T>(T ignored) where T : class а такжеstatic void CallFunctionWithInference<T>(T ignored) where T : class, Еще раз спасибо! Я хотел бы иметь больше, чем +1. Travis J
0

Вы должны быть в состоянии вызвать функцию, как это

callFunction<dynamic>();

Если ваша функция определяется как

public void callFunction<T>(T arg) {
    ...
}

Вы можете просто позвонить с

callFunction(x);

C # может выводить параметры универсального типа во многих ситуациях.

4

Трудно сказать, что именно вы пытаетесь сделать. Но если вы хотите вызвать универсальный метод с параметром типа, который совпадает с некоторым объектом, вы не можете сделать это напрямую. Но вы можете написать другой метод, который принимает ваш объект в качестве параметра,dynamic выведите тип и затем вызовите нужный метод:

void HelperMethod<T>(T obj)
{
    CallFunction<T>();
}

…

dynamic x = …;
HelperMethod(x);
Ничего себе .. это потрясающе .. Тонкая разница в том, что когдаx имеет значение null, механизм вывода типов здесь не работает. Еслиx строго типизирован, сам вызов метода не потерпит неудачу. Просто что-то иметь в виду ..
0

Самый быстрый способ сделать эту работу - сделать ваш анонимный тип настоящим типом.

Так что вместо

var x = new { Value = "somevalue", Text = "sometext" };

Вам нужно сделать

class MyClass
{
    string Text, Value;
}
....
var x = new MyClass() { Value = "somevalue", Text = "sometext" };
//this should work now
callFunction<MyClass>(x);
Обратите внимание, чтоx все еще строго напечатан в первом фрагменте кода; однако тип является анонимным.
2

Вы не можете ". Весь смысл обобщений заключается в безопасности во время компиляции, что означает, что они должны быть известны во время компиляции. И все дело в том, что вам не нужно знать точный тип во время компиляции и использовать диспетчерскую диспетчеризацию = & gt; это абсолютно точная противоположность дженериков. Так что не тратьте свое время = & gt; как только вы получите динамический путь / путь отражения, вы можете забыть об обобщениях и безопасности во время компиляции. Вам придется идти по этому пути до конца.

Итак, чтобы ответить на ваш вопрос:

What can I do to x to make it legitimate enough to be used in ?

Единственное, что вы можете сделать, это использовать тип, который известен во время компиляции, иначе вы не сможете использовать обобщенные типы.

Ну, вы можете использовать дженерики с типом, который не известен во время компиляции, см. Мой ответ.
1

Вы получаете эту ошибку, потому чтоx это не тип. Вам нужно указать тип какtype параметр.

На самом деле, выcan использованиеdynamic в качестве параметра типа, если вы используете его правильно:

var dict = new Dictionary<string, dynamic>();

dict.Add("Item1", 123);
dict.Add("Item2", "Blah");

Это компилируется и работает просто отлично.

Похожие вопросы