Почему аргумент типа не может быть выведен из использования, если ограничение аргумента типа указывает тип? - PullRequest
0 голосов
/ 14 декабря 2018

Я создал метод расширения, который должен предоставлять текст заголовка таблицы для таблицы, содержащей коллекцию элементов типа IList<T>.Хотя компилятор говорит, что TModel не может быть выведен из использования, однако для меня очевидно, что ограничение аргумента типа говорит, что TListModel является IList<TModel>, тогда TModel действительно может быть выведено.

public static MvcHtmlString HeaderFor<TListModel, TModel, TValue>(this HtmlHelper<TListModel> listViewModel, Expression<Func<TModel, TValue>> expression) 
    where TListModel : IList<TModel> 

TListModel - это, скажем, List<Product>, поэтому TModel - это Product, и поэтому я хотел бы использовать HtmlHelper следующим образом:

<th scope="col" class="azonosito">
     @Html.HeaderFor(x => x.Price)
</th>

Теперь мне нужноиспользуйте это так, что так неловко:

<th scope="col" class="azonosito">
     @Html.HeaderFor((Product x) => x.Price)
</th>

1 Ответ

0 голосов
/ 14 декабря 2018

Это запрос, который ранее был сделан для языковой команды C #: ЗАПРОС: сопоставление с образцом / лучший вывод типа с помощью обобщений.# 5023 .Тем не менее, обратите внимание на связанный комментарий, это вносит серьезные изменения, поэтому в настоящее время не реализовано.Смотрите также https://github.com/dotnet/roslyn/issues/11242.

Проблема в том, что компилятор не может определить тип TListModel, может быть только IList<TModel>.Он не понимает, что существует связь между членами списка (IList<TModel>) и контейнером (TListModel).

Есть несколько способов справиться с этим.Один из них, как вы обнаружили, явно указывает тип лямбда-выражения, хотя вы также можете явно указать аргументы типа: @{Html.HeaderFor<IList<SomeModel>, SomeModel, int>(x => x.Price)}.

Для практического решения вы можете изменить определение метода расширения.Это изменение должно предоставлять тип члена как часть параметров метода расширения.

public static MvcHtmlString HeaderFor<TModel, TValue>(this HtmlHelper<IList<TModel>> listViewModel, Expression<Func<TModel, TValue>> expression)
{
    return new MvcHtmlString("a");
}  

Это позволяет неявный вывод типа без ошибок компилятора:

@model IList<SomeModel>
...
@Html.HeaderFor(x => x.Price)

дальнейшее чтение: Как я могу вернуть: где TEnumerable: IEnumerable , см. ответ Джона Скита.

...