InvalidCastException:无法将泛型列表转换为对象
InvalidCastException: Unable cast generic List to object
有人可以向我解释为什么以下转换不起作用以及问题的解决方案。
我有一个 GroupedResult
:
public class GroupedResult<TKey, TElement>
{
public TKey Key { get; set; }
private readonly IEnumerable<TElement> source;
public GroupedResult(TKey key, IEnumerable<TElement> source)
{
this.source = source;
this.Key = key;
}
}
public class Bacon
{
}
我想将 List<string, Bacon>
转换为 List<string, object>
。我尝试了以下和其他方法。
var list = new List<GroupedResult<string, Bacon>>
{
new GroupedResult<string, Bacon>("1", new List<Bacon>()),
new GroupedResult<string, Bacon>("2", new List<Bacon>())
};
var result = list.Cast<GroupedResult<string, object>>().ToList();
但我总是得到以下错误:
InvalidCastException: Unable to cast object of type 'GroupedResult2[System.String,UserQuery+Bacon]' to type 'GroupedResult
2[System.String,System.Object]'.
最好从 GroupedResult 开始然后你可以这样做
new GroupedResult<string, object>("2", new List<Bacon>())
为什么不使用 GroupedResult<string, object>
而不是 GroupedResult<string, Bacon>
?像这样:
var list = new List<GroupedResult<string, object>>
{
new GroupedResult<string, object>("1", new List<Bacon>()),
new GroupedResult<string, object>("2", new List<Bacon>())
};
要实现这一点,您必须使用接口而不是 class 类型。
public interface IGroupResult<TKey, out TElement>
{
TKey Key { get; set; }
}
public class GroupedResult<TKey, TElement> : IGroupResult<TKey, TElement>
{
public TKey Key { get; set; }
private readonly IEnumerable<TElement> source;
public GroupedResult(TKey key, IEnumerable<TElement> source)
{
this.source = source;
this.Key = key;
}
}
public class Bacon
{
}
然后你可以这样做
IGroupResult<string, Bacon> g = new GroupedResult<string, Bacon>("1", new List<Bacon>());
var result = (IGroupResult<string, object>)g;
那是因为协变只允许在接口和委托上使用,而不是 classes。请注意,如果类型仅来自接口(方法 return 类型和只读属性),则只应将其标记为协变。
虽然您应该问问自己为什么在使用泛型时要将某些内容强制转换为 object
。泛型的要点是避免必须使用 object
类型作为包罗万象,这可能表明您的设计存在缺陷,您可能需要重新考虑。
您可以在 GroupedResult
class 中使用 Cast
方法并使用它来进行转换!
public class GroupedResult<TKey, TElement>
{
public TKey Key { get; set; }
private readonly IEnumerable<TElement> source;
public GroupedResult(TKey key, IEnumerable<TElement> source)
{
this.source = source;
this.Key = key;
}
public GroupedResult<TKey, object> Cast()
{
return new GroupedResult<TKey, object>(Key, source.Cast<object>());
}
}
public class Bacon
{
}
static void Main(string[] args)
{
var list = new List<GroupedResult<string, Bacon>>
{
new GroupedResult<string, Bacon>("1", new List<Bacon>()),
new GroupedResult<string, Bacon>("2", new List<Bacon>())
};
// var result = list.Cast<GroupedResult<string, object>>().ToList();
List<GroupedResult<string,object>> result = list.Select(B => B.Cast()).ToList();
}
有人可以向我解释为什么以下转换不起作用以及问题的解决方案。
我有一个 GroupedResult
:
public class GroupedResult<TKey, TElement>
{
public TKey Key { get; set; }
private readonly IEnumerable<TElement> source;
public GroupedResult(TKey key, IEnumerable<TElement> source)
{
this.source = source;
this.Key = key;
}
}
public class Bacon
{
}
我想将 List<string, Bacon>
转换为 List<string, object>
。我尝试了以下和其他方法。
var list = new List<GroupedResult<string, Bacon>>
{
new GroupedResult<string, Bacon>("1", new List<Bacon>()),
new GroupedResult<string, Bacon>("2", new List<Bacon>())
};
var result = list.Cast<GroupedResult<string, object>>().ToList();
但我总是得到以下错误:
InvalidCastException: Unable to cast object of type 'GroupedResult
2[System.String,UserQuery+Bacon]' to type 'GroupedResult
2[System.String,System.Object]'.
最好从 GroupedResult
new GroupedResult<string, object>("2", new List<Bacon>())
为什么不使用 GroupedResult<string, object>
而不是 GroupedResult<string, Bacon>
?像这样:
var list = new List<GroupedResult<string, object>>
{
new GroupedResult<string, object>("1", new List<Bacon>()),
new GroupedResult<string, object>("2", new List<Bacon>())
};
要实现这一点,您必须使用接口而不是 class 类型。
public interface IGroupResult<TKey, out TElement>
{
TKey Key { get; set; }
}
public class GroupedResult<TKey, TElement> : IGroupResult<TKey, TElement>
{
public TKey Key { get; set; }
private readonly IEnumerable<TElement> source;
public GroupedResult(TKey key, IEnumerable<TElement> source)
{
this.source = source;
this.Key = key;
}
}
public class Bacon
{
}
然后你可以这样做
IGroupResult<string, Bacon> g = new GroupedResult<string, Bacon>("1", new List<Bacon>());
var result = (IGroupResult<string, object>)g;
那是因为协变只允许在接口和委托上使用,而不是 classes。请注意,如果类型仅来自接口(方法 return 类型和只读属性),则只应将其标记为协变。
虽然您应该问问自己为什么在使用泛型时要将某些内容强制转换为 object
。泛型的要点是避免必须使用 object
类型作为包罗万象,这可能表明您的设计存在缺陷,您可能需要重新考虑。
您可以在 GroupedResult
class 中使用 Cast
方法并使用它来进行转换!
public class GroupedResult<TKey, TElement>
{
public TKey Key { get; set; }
private readonly IEnumerable<TElement> source;
public GroupedResult(TKey key, IEnumerable<TElement> source)
{
this.source = source;
this.Key = key;
}
public GroupedResult<TKey, object> Cast()
{
return new GroupedResult<TKey, object>(Key, source.Cast<object>());
}
}
public class Bacon
{
}
static void Main(string[] args)
{
var list = new List<GroupedResult<string, Bacon>>
{
new GroupedResult<string, Bacon>("1", new List<Bacon>()),
new GroupedResult<string, Bacon>("2", new List<Bacon>())
};
// var result = list.Cast<GroupedResult<string, object>>().ToList();
List<GroupedResult<string,object>> result = list.Select(B => B.Cast()).ToList();
}