windows 如何将对象转换为未知类型 T 的 IList<T>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5770516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:42:54  来源:igfitidea点击:

How to cast a object to IList<T> with unknown type T

c#.netwindowsgenericscasting

提问by alex


I have a object[]containig some values. I want to extract infomation out of it, but I fail at casting the second object in the array (a WeakReference) to a IList with T as the third value in the array.


我有一个object[]包含一些值。我想从中提取信息,但我无法将数组 (a WeakReference) 中的第二个对象转换为 IList,其中 T 作为数组中的第三个值。

Take a look at my code:

看看我的代码:

object[] vals = GetValues(); //vals[2] = WeakReference, vals[3] = Type of T, vals[4] = index in the list
IList<((Type)vals[3])> list = (IList<((Type)vals[3])>)(((WeakReference)vals[2]).Target); //This line does not even compile, seems like I'm doing something wrong..
object oo = list.ElementAt((int)vals[4]);
//Do something with oo...

Any suggestions how I can cast the Target of the WeakReference to a IList interface with T = vals[3] ?

任何建议如何将 WeakReference 的目标转换为 T = vals[3] 的 IList 接口?

回答by Ani

It's really strange that you are packing so much heterogeneous information into an array. Arrays are normally used to store elements of the sametype. Why not encapsulate the data in a proper type?

你把这么多异类信息打包成一个数组真的很奇怪。数组通常用于存储相同类型的元素。为什么不将数据封装在适当的类型中?

But to answer the question as asked - in C# 4, you can use dynamic:

但是要回答所问的问题 - 在 C# 4 中,您可以使用dynamic

var target = ((dynamic)vals[2]).Target;

if(target != null)
{
    object oo = Enumerable.ElementAt(target, vals[4]);
    //Do something with oo...
}

(EDIT: If you want to minimize the use of dynamichere, cast to a WeakReferenceand leave the dynamic call to the end. This way, type-safety is 'maximized'.)

(编辑:如果您想最小化dynamic此处的使用,请强制转换为 aWeakReference并将动态调用保留到最后。这样,类型安全性就“最大化”了。)

Otherwise, you can use reflection:

否则,您可以使用反射:

object target = ((WeakReference)vals[2]).Target;

if (target != null)
{
    object oo = target.GetType()
                      .GetProperty("Item")
                      .GetValue(target, new[] { vals[4] });
    //Do something with oo...
}

(EDIT: If the indexer could be explicitly implemented, you'll probably need to use the interface mappings.)

(编辑:如果可以显式实现索引器,您可能需要使用接口映射。)

回答by Timwi

It was already suggested that you could use dynamic, but it sounds like you are also supposed to check that the object has the specified type. I've also kept use of dynamicto a minimum:

已经建议您可以使用dynamic,但听起来您还应该检查对象是否具有指定的类型。我也dynamic尽量减少使用:

object target = ((WeakReference) vals[2]).Target;

if (target == null)
    throw new InvalidOperationException("Target cannot be null.");

object result = Enumerable.ElementAt((dynamic) target, (int) vals[4]);

if (result != null && !((Type) vals[3]).IsAssignableFrom(result.GetType()))
    throw new InvalidOperationException(string.Format("The retrieved object is a {0}, but the expected type was {1}.", result.GetType(), (Type) vals[3]));

return result;

回答by Simon Mourier

If you just need the object from an enumerable, at a given index, here is a simple function that does it:

如果您只需要在给定索引处的可枚举对象,这里是一个简单的函数:

    public static object GetObjectAt(IEnumerable enumerable, int index)
    {
        int i = 0;
        foreach (object obj in enumerable)
        {
            if (i == index)
                return obj;

            i++;
        }
        throw new IndexOutOfRangeException();
    }

And in your case, you would do this:

在你的情况下,你会这样做:

        object oo = GetObjectAt((IEnumerable)(WeakReference)vals[2], (int)vals[4]);

Of course there are alternatives that look more sexy (see other answers), with fancy linq queries and cool C# 4 dynamic new trendy stuff :-) but, in general, if you don't "need" the T type (in your example code, you don't need it), you don't need generics. This solution is actually supported with any .NET Framework and C# versions, from 1 to 4.

当然,还有一些看起来更性感的替代方案(请参阅其他答案),具有花哨的 linq 查询和酷炫的 C# 4 动态新时尚东西:-) 但是,总的来说,如果您不需要“T”类型(在您的示例中)代码,你不需要它),你不需要泛型。从 1 到 4,任何 .NET Framework 和 C# 版本实际上都支持此解决方案。

回答by tvanfosson

I think you're working too hard to be able to use the extension methods which don't seem to be necessary.

我认为您工作太努力以至于无法使用似乎没有必要的扩展方法。

object[] vals = GetValues();
var list = ((WeakReference)vals[2]).Target as IList;
object oo = null;
if (list != null)
{
    oo = list[(int)vals[4]];
}