我试图了解Enumerable.Cast
执行强制转换的原因,以及为什么即使为目标类型定义了隐式(或显式)转换运算符也无法使其正常工作。
以下代码组合了一些我已经准备了解错误原因的测试。我真正想要的是了解为什么test5
抛出而InvalidCastException
抛出;但是在现阶段,我认为问题与test3
和test4
的失败有关。
void Main()
{
List<Currency> values = new List<Currency>() { new Euro(), new Dollar() };
Dollar d = new Dollar();
Euro e = new Euro();
var test1a = (Dollar)e; // valid
var test1b = (Euro)d; // valid
Console.WriteLine(values[0].GetType()); // Euro
var test2 = values[0] as Dollar; // valid
var test3 = (Dollar)values[0]; // Why does this fail? - InvalidCastException: Unable to cast object of type 'Euro' to type 'Dollar'
var test4 = values.Cast<Euro>(); // no error
Console.WriteLine(test4.ToString()); // what's this CastIterator?
var test5 = test4.ToList(); // Why does this fail? - InvalidCastException: Unable to cast object of type 'Dollar' to type 'Euro'
}
class Currency { public double Amount {get; set;} = 0; }
class Euro : Currency
{
public Euro(double amount = 0) { this.Amount = amount; }
public static implicit operator Euro(Dollar d)
{
Euro e = new Euro(); e.Amount = d.Amount*1.2; return e;
}
}
class Dollar : Currency
{
public Dollar(double amount = 0) { this.Amount = amount; }
public static implicit operator Dollar(Euro e)
{
Dollar d = new Dollar(); d.Amount = e.Amount/1.2; return d;
}
}
如您所见,我已经为类指定了隐式转换运算符,但是,这不足以使test3和4正常工作。 这是为什么?
答案 0 :(得分:0)
如果您想知道LINQ函数的作用,请随时访问reference source in Enumerable.CS
在这里您会找到:
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
{
IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
if (typedSource != null) return typedSource;
if (source == null) throw Error.ArgumentNull("source");
return CastIterator<TResult>(source);
}
static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source)
{
foreach (object obj in source)
{
yield return (TResult)obj;
}
}
那么,对于源序列中的每个对象,它将执行:
(TResult) obj;
要找出出现问题的原因,只需创建您的来源列表,然后开始列举自己:
List<Currency> currencies = ...
foreach (Currency currency in currencies)
{
Dollar d = (Dollar)currency;
Euro e = (Euro) currency;
Console.WriteLine("Dollar {0}; Euro {1}", d, e);
}
您的调试器会告诉您哪里出了问题。
var test2 = values[0] as Dollar; // valid
var test3 = (Dollar)values[0]; // InvalidCastException
test3是否意味着:( (Dollar)values ) [0];
。如果加上括号,是否可以解决问题?
var test3 = (Dollar) (values[0]);