IEnumerable <T>.Cast не будет работать, даже если определен явный оператор литья?
У меня есть явное преобразование, определенное из типа Bar
, чтобы напечатать Foo
.
public class Bar
{
public static explicit operator Foo(Bar bar)
{
return new Foo(bar.Gar);
}
}
public class Foo
{
public string Gar { get; set; }
public Foo() { }
public Foo(string gar) { Gar = gar; }
}
Однако, когда я это делаю:
using System.Linq;
...
var manyFoos = manyBars.Cast<Foo>();
Он выдает исключение, говорящее, что он не может использовать.
Как мне сказать Cast
использовать мой оператор трансляции, чтобы попробовать преобразовать?
Ответы
Ответ 1
Операторы роли - это статические методы, которые вызывает компилятор при использовании бросков в коде. Они не могут использоваться динамически. Enumerable.Cast
выполняет время выполнения из двух неограниченных общих типов, поэтому во время компиляции, которые используют операторы-листы, он не может знать. Чтобы сделать то, что вы хотите, вы можете использовать Select
:
manyFoos.Select(foo => (Bar)foo);
Ответ 2
Метод linq Cast
по существу делает поле и unbox. Он не знает ни о неявных, ни явных операторах литья, определенных в С#, которые компилятор рассматривает стандартные вызовы методов.
Вам нужно будет сделать что-то вроде этого:
var manyFoos = manyBars.Select(bar => (Foo)bar);
Ответ 3
Как и во всех других ответах, тиковый тип не известен во время компиляции, так как Cast
метод не generic
. Он содержит тип object
и делает явное приведение к T
. это не работает, потому что у вас нет оператора преобразования от object
до Foo
. И это также невозможно.
Вот работа с использованием динамики, в которой литье будет выполняться во время выполнения.
public static class DynamicEnumerable
{
public static IEnumerable<T> DynamicCast<T>(this IEnumerable source)
{
foreach (dynamic current in source)
{
yield return (T)(current);
}
}
}
Затем используйте его как
var result = bars.DynamicCast<Foo>();//this works
Ответ 4
Используйте Select
:
var manyFoos = manyBars.Select(bar => (Foo)bar);
Ответ 5
Ваш код фактически не компилируется. Я предполагаю, что в классе "Бар" есть свойство "Гар"?
public class Bar
{
public string Gar { get; set; }
public static explicit operator Foo(Bar bar)
{
return new Foo(bar.Gar);
}
}
public class Foo
{
public string Gar { get; set; }
public Foo() { }
public Foo(string gar) { Gar = gar; }
}
static void Main(string[] args)
{
List<Bar> bars = new List<Bar>();
for (int i = 0; i < 10; i++)
bars.Add(new Bar() { Gar = i.ToString() });
var result = bars.Cast<Foo>();
}
+
Я обманываю вас, чтобы прочитать о ковариации.
Предполагая, что A можно сместить в B, X ковариантно, если X<A>
можно преобразовать в X<B>
.
С понятием С# ковариации (и контравариантности) термин "конвертируемый" означает конвертируемое через неявное ссылочное преобразование, такое как A-подкласс B или реализация B. B. Числовые преобразования, преобразования бокса и пользовательские преобразования не включены.
Вы должны сделать это с помощью интерфейсов.