Не удается преобразовать тип выражения в возвращаемый тип

У меня есть следующий метод, который работает:

public Option<IAppSettings> GetFirst<T>() where T : IAppSettings
{
  return _sources.Where(x=>x.GetType() == typeof(T)).FirstOption();
}

List<IAppSettings> _sources;

Но я хочу изменить подпись на:

public Option<T> GetFirst<T>() where T : IAppSettings

Обратите внимание, что я возвращаю общий T вместо IAppSettings

Я получаю сообщение об ошибке (усеченные типы):

Невозможно преобразовать тип выражения Option<IAppSettings> в Option<T>

Я знаю, что это как-то связано с дженериками, но, по общему признанию, отстой в них... Я пробовал разные средства in, out, interface, delegate... но ни один из них не работал, так как это метод на неуниверсальном класс с использованием переменной экземпляра.

Это вообще возможно?

Обновленные мысли

Должен ли я изменить спецификации типа в Option? Если да, то я предполагаю, что это должно быть Option<in T>? Я говорю это только потому, что Option в Scala имеет тип Option[+A]. У меня есть исходный код для Option, но его трудно изменить и подтолкнуть... поэтому я решил сначала спросить здесь, но попробую это дальше

Этот Option взят из моего форка Scalesque


person Justin Pihony    schedule 16.04.2015    source источник
comment
Это может зависеть от того, какие дженерики допускают. Варианта нет? применяется одинаково?   -  person Juan Pablo Garcia Coello    schedule 16.04.2015
comment
Трудно сказать только по небольшим фрагментам. Например, содержит ли содержащий класс также универсальный аргумент T? Например, public class Parent<T>{} ? В этом случае этот общий тип может влиять на метод.   -  person Travis J    schedule 16.04.2015
comment
@TravisJ Я сказал, что содержащий класс не является универсальным. Я только что обновил, чтобы прояснить, что sources это List<IAppSettings>, хотя   -  person Justin Pihony    schedule 16.04.2015
comment
Что произойдет, если вы добавите .OfType‹T›() перед .FirstOption()?   -  person Glorfindel    schedule 16.04.2015
comment
@Glorfindel Это исправлено! Отправьте в качестве ответа, и я приму   -  person Justin Pihony    schedule 16.04.2015


Ответы (2)


Вы ищете Enumerable.OfType метод. Это должно заменить ваш метод Where().

https://msdn.microsoft.com/en-us/library/vstudio/bb360913(v=vs.100).aspx

Проблема, с которой вы сталкиваетесь, заключается в том, что простая проверка типа «если» на самом деле не приведет к приведению его к T; как только он проходит эту фильтрацию, объекты коллекции по-прежнему известны только как тип IAppSettings. Стандартная функция С#, о которой я упоминал, сделает это за вас.

person Katana314    schedule 16.04.2015
comment
Я могу создать отдельный тикет, но было любопытно, знаете ли вы, зачем мне нужен OfType? T должен быть IAppSetting, поэтому он должен быть преобразован автоматически. Есть ли какой-то вариант использования, о котором я не думаю, что он сломается, если это будет реализовано? - person Justin Pihony; 21.04.2015
comment
Определение Where состоит в том, чтобы взять лямбду, которая принимает тип коллекции и возвращает логическое значение. Его возвращаемый тип всегда является общей коллекцией того же типа, что и коллекция, над которой он работает, и не более того. Он не анализирует лямбду, которую вы ему дали, чтобы выяснить, какой точный тип вы можете вернуть (черт возьми, лямбда может быть переменной). Если бы ваше предложение Where было x -> x.toString().contains("cheese"), то оно также ничего не сделало бы для повышения специфичности типов; у вас все равно будет только коллекция IAppSettings, а не коллекция T. - person Katana314; 21.04.2015
comment
Я понимаю это, но T ограничен IAppSettings, поэтому он возвращает IAppSettings и ожидает T: IAppSettings. - person Justin Pihony; 21.04.2015
comment
А также? Какое отношение T имеет к возвращаемому типу Where()? Where() не меняет тип коллекции; поэтому, если вы вызвали GetFirst<VerySpecificAppSettings>() и вернули _sources, он не смог бы скомпилироваться, потому что вы не знаете наверняка, что _sources содержит только VerySpecificAppSettings; вы просто знаете, что он содержит IAppSettings. - person Katana314; 21.04.2015
comment
Правда, от дисперсии у меня всегда голова закружилась. Это и Лисков мой ответ. Спасибо - person Justin Pihony; 21.04.2015

Добавьте .OfType() перед .FirstOption().

person Glorfindel    schedule 16.04.2015