如何从列表与所述返回对象的特定类型;对象> [英] How to return a specific type of object from List<object>

查看:108
本文介绍了如何从列表与所述返回对象的特定类型;对象>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名单,其中,对象> 这是不同类型的对象的集合。

I have a List<object> which is a collection of various type of objects.

我写一个辅助方法,该方法将返回对象的特定类型。该helper方法接受类型名称作为字符串参数。

I am writing a helper method which will return a specific type of object. The helper method will accept type name as string parameter.

注:我用的3.5框架

推荐答案

如果您需要使用的字符串作为参数,则不能依靠 OfType&LT; T&GT;( )扩展方法。幸运的是很容易的的emulate 的:

If you need to use a string as parameter you can't rely on OfType<T>() extension method. Fortunately it's easy to emulate:

public IEnumerable<object> OfType(this List<object> list, string typeName)
{
    return list.Where(x => x != null && x.GetType().Name == typeName);
}

由于在评论中指出@ChrisSinclair该解决方案不管理的转换,注塑和继承/接口。强制类型转换(因为用户自定义转换操作符)和转换(因为类型转换器 S和 IConvertible 接口)是有点更棘手。对于简单的(隐含的)管型(如继承和接口),可以使用这样的:

As pointed out by @ChrisSinclair in the comment this solution does not manage conversions, casts and inheritance/interfaces. Casts (because of user defined conversion operators) and conversions (because of TypeConverters and the IConvertible interface) are little bit more tricky. For simple (implicit) casts (like with inheritance and interfaces) you can use this:

public IEnumerable<object> OfType(this List<object> list, string typeName)
{
    Type type = Type.GetType(typeName);
    return list.Where(x => x != null && type.IsAssignableFrom(x.GetType()));
}

如何执行转换(甚至自定义转换操作符)在运行时

我发现我需要的东西,如code我张贴在这个答案,但我不得不延长一点点,这里更好的实现,需要照顾的自定义类型转换和转换。

I found I needed something like the code I posted in this answer but I had to extend it a little bit, here a better implementation that takes care of custom casts and conversions.

CastExtensions 类中把一切(或更新code,如果你不)则宣布这个小枚举其选项:

Put everything inside a CastExtensions class (or update code if you don't) then declare this small enum for its options:

[Flags]
public enum CastOptions
{
    None = 0,
    ExcludeNulls = 1,
    UseConversions = 2
}

问题的是,C#,一般是静态类型语言,这意味着几乎所有(关于类型)必须在编译时是已知的(再进行类型转换,你必须知道键入您要转换为在编译时)。这个函数处理的简单的情况下(如偏差),更复杂的(界面,自定义转换运营商 - 广播 - 和转换 - 在需要时)。

The problem is that C# in general is a statically typed language, it means that almost everything (about types) must be known at compile time (then to perform a cast you have to know type your want to cast to at compile time). This function handles simple cases (like derivation) and more complex ones (interfaces, custom conversion operators - casts - and conversions - when required).

public static IEnumerable<object> OfType(this List<object> list, 
                                         string typeName, CastOptions options)
{
    Type type = Type.GetType(typeName);

    foreach (var obj in list)
    {
        if (Object.ReferenceEquals(obj, null))
        {
            if (options.HasFlag(CastOptions.ExcludeNulls))
                continue;

            yield return obj;
        }

        var objectType = obj.GetType();

        // Derived type?
        if (type.IsAssignableFrom(objectType))
            yield return obj;

        // Should we try to convert?
        if (!options.HasFlag(CastOptions.UseConversions))
            continue;

        // Castable?
        object convertedValue = null;

        try
        {
            var method = typeof(CastExtensions)
                .GetMethod("Cast", BindingFlags.Static|BindingFlags.NonPublic)
                .MakeGenericMethod(type);

            convertedValue = method.Invoke(null, new object[] { obj });
        }
        catch (InvalidCastException)
        {
            // No implicit/explicit conversion operators
        }

        if (convertedValue != null)
            yield return convertedValue;

        // Convertible?
        if (options.HasFlag(CastOptions.UseConversions))
        {
            try
            {
                IConvertible convertible = obj as IConvertible;
                if (convertible != null)
                    convertible.ToType(type, CultureInfo.CurrentCulture);
            }
            catch (Exception)
            {
                // Exact exception depends on the source object type
            }
        }
    }
}

注意的转换的可能,或不等同于一个演员,其实这取决于 实施和参与行动的确切类型(这就是为什么你 可以启用或通过选项禁用此的功能的)。

Note that conversion may be or not equivalent to a cast, actually it depends on the implementation and the exact types involved in the operation (that's why you can enable or disable this feature through options).

这是在运行时所需要的投小助手功能:

This is a small helper function needed for cast at run-time:

private static T Cast<T>(object obj)
{
    return (T)obj;
}

我们可能会发出这样code运行时(我估计即使使用EX pressions,但我没有尝试),但一个小的辅助方法,将产生正是我们所需要的code(从转换一个目的是一个通用的,在运行时类型已知的)。请注意,这的铸造的功能并不如预期的值类型的工作,例如:

We may emit this code at run-time (I suppose even using expressions but I didn't try) but a small helper method will generate exactly the code we need (conversion from an object to a generic known at run-time type). Note that this cast function doesn't work as expected for value types, for example:

int a = 1;
float a = Cast<float>(a); // Run-time error

这是因为(对象)1 不能转换到别的比 INT (这是适用于所有装箱的值类型)。如果你正在使用C#4.0,你应该改变对象参数 OBJ 动态,一切会正常运行(对于所有类型)。

This is because (object)1 cannot be converted to anything else than int (this is true for all boxed value types). If you're using C# 4.0 you should change object for parameter obj to dynamic and everything will work as expected (for all types).

这篇关于如何从列表与所述返回对象的特定类型;对象&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆