【发布时间】:2019-11-23 13:42:36
【问题描述】:
考虑以下代码:
public interface ITest
{
public string Id { get; set; }
}
public class MyObject : ITest {
{
public string Id { get; set; }
public string Value { get; set; }
}
public void Run()
{
IList<MyOBject> myObjects = GetMyObjects();
myObjects = GetTestITems(myObjects);
}
public IList<ITest> GetTestItems(IList<ITest> items)
{
//run some logic
return items;
}
上面的代码会失败两次。第一次是尝试将IList<MyObject> 转换为IList<ITest>,然后尝试转换回IList<MyObject>。但是,如果我将代码更改为以下代码,则它可以工作:
public void Run()
{
IList<MyOBject> myObjects = GetMyObjects();
var myTests = new List<ITest>();
foreach(var o in myObjects) {
myTests.Add(o);
}
var result = GetTestITems(myTests);
myObjects = new List<MyObject>();
foreach(var r in result) {
myObjects.Add(r);
}
}
有没有一种方法可以实现这一点而不必像这样循环两次?也许是一种 linq 方式或某种形式的铸造?我尝试过直接强制转换,但在两个实例上都失败了,转到 ITest 并返回到 MyObject。
【问题讨论】:
-
你能用 IEnumerable
代替 IList 吗? -
@user1781290 在哪个部分?
-
如果你可以将 public IList
GetTestItems(IList items) 更改为 public IEnumerable GetTestItems(IEnumerable items) 你应该没问题。如果没有,您需要创建一个新列表 -
如果您可以使用
IReadOnlyList<T>作为GetTestItems()的参数,那将解决您一半的担忧。另一半是棘手的,原因在涉及类型参数差异的大量现有 Stack Overflow 帖子中进行了解释,包括标记的重复项(在网站上有一些更广泛的解释)。当类型参数T不同时,即使从IReadOnlyList<T>回退也根本不是类型安全的,更不用说IList<T>。 -
同意@PeterDuniho。在
T中使用协变(“out”)的IReadOnlyList<out T>免费获得安全转换。你不能做的不安全的方式。如果您坚持,您可以将.Cast<MyObject>()用作不同的语法,但它仍然会遍历列表,并且当/如果您遇到恰好不是MyObject的ITest时它会爆炸。