2014-02-07 4 views
4

Почему возможно преобразование в строку «ОК», а не в строке «НЕ ОК»?IQueryable convertions

var queryable = new int[]{1, 2, 3}.AsQueryable(); 

var x = (Expression<Func<IQueryable<int>>>)(() => (from c in queryable select c)); 

var yy = (Expression<Func<IEnumerable<int>>>)x; // NOT OK (does not compile) 
var zz = (Expression<Func<IEnumerable<int>>>)(() => (from c in queryable select c)); // OK 

Update: Сообщение об ошибке:

Не удается преобразовать тип System.Linq.Expressions.Expression<System.Func<System.Linq.IQueryable<int>>> в 'System.Linq.Expressions.Expression<System.Func<System.Collections.Generic.IEnumerable<int>>>'

+1

обеспечивает соответствующее сообщение об ошибке. – Samuel

+0

Полный учебник по ковариации смотрите здесь: [MSDN: ковариация и контравариантность в универсалах] (http://msdn.microsoft.com/en-us/library/dd799517 (v = vs.110) .aspx) – pid

ответ

3

Потому что Expression является классом и IEnumerable является интерфейсом. А классы не ковариантны, а интерфейсы и делегаты.

Это означает, что вы не можете преобразовать Expression<A> в Expression<B>, даже если B является базовым классом А.

Так что, если эта линия:

() => (from c in queryable select c) 

возвращает

Func<IQueryable<int>> 

он может быть преобразован в

Func<IEnumerable<int>> 

, но если у вас уже есть

Expression<Func<IQueryable<int>>> 

он не может быть преобразован в

Expression<Func<IEnumerable<int>>> 
+1

@ l3arnon : вы сказали * IEnumerable и IQueryable уже ковариант *, что заставило меня переосмыслить все это. Вы правы, сэр! – pid

+0

@pid 'Func' также. Вы можете видеть, что он использует ключевые слова 'in' или' out' в определении типа. http://msdn.microsoft.com/en-us/library/bb549151(v=vs.110).aspx – i3arnon

+0

И как представлен лямбда? Я думал, что либо Func >, либо выражение >>. – user3284063

1

Expression<T> класс и, следовательно, не ковариантны.

Вы можете сделать следующее:

Func<IQueryable<int>> qf =() => queryable.Select(c => c); 
Func<IEnumerable<int>> ef = qf; 

Однако, поскольку классы не КОВАРИАНТНОЙ в C#, вы не можете назначить Expression<T> к Expression<U>, даже если вы можете назначить экземпляр T для U;

Смежные вопросы