如何从列表与所述返回对象的特定类型;对象&gt; [英] How to return a specific type of object from List<object>
问题描述
我有一个名单,其中,对象&gt;
这是不同类型的对象的集合。
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 TypeConverter
s 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屋!