[英]C# Cast List of MyType to List of objects
I'm writing an application where I am required to use Reflection to call a method which has parameters of type MyObject. 我正在编写一个应用程序,我需要使用Reflection来调用一个具有MyObject类型参数的方法。
Method (List<MyObject> input , out List<MyObject> output,..... );
Using reflection I send the parameter of type Object. 使用反射我发送Object类型的参数。 How can I cast
List<MyObject>
to List<object>
如何将
List<MyObject>
为List<object>
var parameters = new Object[] { inputs, outputs, userPrams };
System.Type classType = typeof(MyClass);
object instance = Activator.CreateInstance(classType);
classType.InvokeMember(name, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,null, instance, parameters);
In the code above both input and output are lists of type MyObject 在上面的代码中,输入和输出都是MyObject类型的列表
I tried to Cast them to List of Objects but this doesn't work 我试图将它们转换为对象列表,但这不起作用
x.Outputs = grOutputs as IList<object>
Can anyone help? 有人可以帮忙吗?
Your question is not 100% clear, so I assumed the problem you're facing is the one you put in the title: 你的问题不是100%明确,所以我认为你面临的问题是你在标题中提出的问题:
Cast List of MyType to List of objects
将MyType的列表转换为对象列表
As @Charles said, IList<T>
and List<T>
are not variant, so you can't cast IList<DerivedClass>
to IList<BaseClass>
. 正如@Charles所说,
IList<T>
和List<T>
不是变体,因此您无法将IList<DerivedClass>
为IList<BaseClass>
。 You have to create new List<BaseClass>
. 您必须创建新的
List<BaseClass>
。
There are many ways to do that, I think there are two you should consider: 有很多方法可以做到这一点,我认为你应该考虑两个:
You can use Cast
and ToList
, but it will require using System.Linq
. 您可以使用
Cast
和ToList
,但需要using System.Linq
。
var listOfStrings = new List<string>() { "foo", "bar" }; var listOfObjects = listOfStrings.Cast<object>().ToList();
To avoid that, you can use new List<T>(IEnumerable<T> source)
constructor. 为避免这种情况,您可以使用
new List<T>(IEnumerable<T> source)
构造函数。 Because IEnumerable<T>
is covariant, you can do following: 因为
IEnumerable<T>
是协变的,所以你可以这样做:
var listOfStrings = new List<string>() { "foo", "bar" }; var listOfObjects = new List<object>(listOfString);
You might well want to do something like this: 你可能想做这样的事情:
var dogs = new List<Dog>();
var pets = (List<object>)dogs;
pets.Add(new Cat());
The C# language is heavily invested in you stop mixing cats and dogs like this. C#语言投入大量资金用于停止像这样的猫狗混合。 It violates the hard guarantee that the list only ever contains dogs.
它违反了列表只包含狗的硬保证。 You'll have to do it like this instead:
你必须这样做:
var dogs = new List<Dog>();
var pets = new List<object>(dogs);
pets.Add(new Cat());
Which is fine, it creates a new list, one that no longer guarantees that it only ever contains dogs since it only promises that the list contains object . 哪个好,它会创建一个新的列表,不再保证它只包含狗,因为它只承诺列表包含对象 。 Pretty useless, typically, you basically lose all knowledge of what the list contains.
相当无用,通常,你基本上都不知道列表包含的内容。 Forcing you to write hunt-the-fox code that uses the as operator or Reflection to find the proper animal back.
强迫你编写使用as运算符或Reflection的hunt-the-fox代码来找回适当的动物。 Code that fails to do its job at run-time instead of the compiler telling you that its wrong code at build time, when you're still in the comfortable cubicle cocoon.
代码在运行时无法完成其工作,而不是编译器在构建时告诉您错误的代码,当您仍在舒适的隔间茧中时。
Which it did. 它做了什么。
IList<T>
不是协变的,如果你想要IList<object>
,你需要创建一个新的列表:
x.Outputs = grOutputs.Cast<object>().ToList();
You cannot make your desired cast because, as others have written, collections in c# are not covariant . 您无法进行所需的演员表,因为正如其他人所写,c#中的集合不是协变的 。
You can either create a new list, or introduce a ListWrapper class like so: 您可以创建新列表,也可以像这样引入ListWrapper类:
public class ListWrapper<TOut, TIn> : IList<TOut> where TIn : class, TOut where TOut : class
{
readonly IList<TIn> list;
public ListWrapper(IList<TIn> list)
{
if (list == null)
throw new NullReferenceException();
this.list = list;
}
#region IList<TOut> Members
public int IndexOf(TOut item)
{
TIn itemIn = item as TIn;
if (itemIn != item)
return -1;
return list.IndexOf(itemIn);
}
public void Insert(int index, TOut item)
{
list.Insert(index, (TIn)item);
}
public void RemoveAt(int index)
{
list.RemoveAt(index);
}
public TOut this[int index]
{
get
{
return list[index];
}
set
{
list[index] = (TIn)value;
}
}
#endregion
#region ICollection<TOut> Members
public void Add(TOut item)
{
list.Add((TIn)item);
}
public void Clear()
{
list.Clear();
}
public bool Contains(TOut item)
{
TIn itemIn = item as TIn;
if (itemIn != item)
return false;
return list.Contains(itemIn);
}
public void CopyTo(TOut[] array, int arrayIndex)
{
foreach (var item in list)
{
array[arrayIndex] = item;
arrayIndex++;
}
}
public int Count
{
get { return list.Count; }
}
public bool IsReadOnly
{
get
{
return list.IsReadOnly;
}
}
public bool Remove(TOut item)
{
return list.Remove(item as TIn);
}
#endregion
#region IEnumerable<TOut> Members
public IEnumerator<TOut> GetEnumerator()
{
foreach (var item in list)
yield return item;
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
You might want to make the wrapper read-only since the setter could throw an exception if the incoming object is not of the inner list's item type. 您可能希望将包装器设置为只读,因为如果传入的对象不是内部列表的项类型,则setter可能会抛出异常。
如果我理解你的问题,你可以尝试这样的事情:
var objList = myClassList.OfType<object>();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.