Почему происходит сбой операции Linq Cast <T>, когда определено неявное приведение? - PullRequest
17 голосов
/ 30 апреля 2009

Я создал два класса, один из которых имеет неявное приведение между ними:

public class Class1
{
    public int Test1;
}

public class Class2
{
    public int Test2;

    public static implicit operator Class1(Class2 item)
    {
        return new Class1{Test1 = item.Test2};
    }
}

Когда я создаю новый список одного типа и пытаюсь привести к другому, происходит сбой с InvalidCastException:

List<Class2> items = new List<Class2>{new Class2{Test2 = 9}};
foreach (Class1 item in items.Cast<Class1>())
{
    Console.WriteLine(item.Test1);
}

Это, однако, отлично работает:

foreach (Class1 item in items)
{
    Console.WriteLine(item.Test1);
}

Почему неявное приведение не вызывается при использовании Cast ?

Ответы [ 4 ]

6 голосов
/ 01 мая 2009

Поскольку, просматривая код с помощью Reflector, Cast не пытается учесть какие-либо неявные операторы приведения (код LINQ Cast сильно оптимизирован для особых случаев всех видов, но ничего в этом направлении) во внимание (как и во многих других языках .NET). не будет).

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

РЕДАКТИРОВАТЬ: Как правило, более сложные средства, такие как неявные / явные, операторы равенства и т. Д., Обычно не обрабатываются общими средствами, такими как LINQ.

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

Вы также можете использовать это для приведения с преобразованием, если необходимо:

public static IEnumerable<TDest> CastAll<TItem, TDest>(this IEnumerable<TItem> items)
{
 var p = Expression.Parameter(typeof(TItem), "i");
 var c = Expression.Convert(p, typeof(TDest));
 var ex = Expression.Lambda<Func<TItem, TDest>>(c, p).Compile();

 foreach (var item in items)
 {
    yield return ex(item);
 }
}

С http://adventuresdotnet.blogspot.com/2010/06/better-more-type-safe-alternative-to.html

1 голос
/ 01 мая 2009

Спасибо за то, что я собирался использовать этот конкретный случай где-нибудь. Вы сэкономили мне кучу времени. В качестве возможного решения вашей проблемы вы можете использовать ConvertAll <>, например, так:

foreach (Class1 item in items.ConvertAll<Class1>((i) => (Class1)i))
{
     Console.WriteLine(item.Test1);
}

РЕДАКТИРОВАТЬ: или если вы хотите быть более явным, что приведение неявно, то это также работает:

foreach (Class1 item in items.ConvertAll<Class1>(i => i))
{
     Console.WriteLine(item.Test1);
}
0 голосов
/ 16 мая 2010

Решением может быть использование небольшого количества ссылок здесь, если вам действительно нужен такой вид преобразования:

List items = new List{new Class2{Test2 = 9}};
foreach (Class1 item in (from x in items select (Class1)x))
{
    Console.WriteLine(item.Test1);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...