[英]Safely cast a Generic type in C#
How can I safely cast and return m_obj depending on the given Generic type. 如何根据给定的泛型类型安全地强制转换并返回m_obj。
private IObject m_obj;
public bool TryGetAs<T>(out T value) where T :IObject
{
value = m_obj as T; // The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint
// value = (T)m_obj; This compiles!
if (value != null)
return true;
return false;
}
I know that if instead if m_obj I had a list I could simply do this: 我知道,如果相反,如果m_obj我有一个列表,我可以简单地做到这一点:
private readonly IList<Object> m_objects;
internal IList<T> Collect<T>() where T : IObject
{
return m_objects.OfType<T>().ToList();
}
But I cannot find a solution for the former code. 但是我找不到以前的代码的解决方案。
public interface IObject
{
}
My answer: 我的答案:
public bool TryGetAs<T>(out T value) where T :IObject
{
value = default(T);
if (!(m_obj is T))
return false;
value = (T)m_obj;
return true;
}
The as
keyword works with reference types. as
关键字适用于引用类型。
The compiler doesn't know that T
is indeed a reference type, so it shouts at you and won't compile. 编译器不知道
T
确实是引用类型,因此它会向您喊叫并且不会编译。
You can tell the compiler that it's a reference type by adding the class
constraint before the IObject
constraint. 通过在
IObject
约束之前添加class
约束 ,可以告诉编译器它是引用类型。 Now you can safely cast. 现在您可以放心了。
The as
operator is reserved for reference types. as
运算符保留用于引用类型。 If T
is always a reference type, the solution is to add a class
constraint to TryGetAs<T>
. 如果
T
始终是引用类型,则解决方案是向TryGetAs<T>
添加class
约束。 If T
can also be a value type, this is not an option. 如果
T
也可以是值类型,则这不是选项。 In this case you can use the is
operator: 在这种情况下,可以使用
is
运算符:
public bool TryGetAs<T>(out T value) where T : IObject
{
if(m_obj is T)
{
value = (T)m_obj;
return true;
}
else
{
value = default(T);
return false;
}
}
In C# 7.0 you can simplify it like this (and improve performance since you don't need an is
cast and then another type cast): 在C#7.0,你可以把它简化像这样(和提高性能,因为你并不需要的
is
投再另一种类型的施法):
public bool TryGetAs<T>(out T value) where T : IObject
{
if(m_obj is T tValue)
{
value = tValue;
return true;
}
else
{
value = default(T);
return false;
}
}
public bool TryGetAs<T>(out T value) where T : class, IObject
{
value = m_obj as T;
return (value != null);
}
will act the same as your final solution, as well as likely being faster (since a null check is faster than an is
check). 将与最终解决方案一样,并且可能更快(因为空检查比
is
检查更快)。
There is no benefit in not including the class
modifier, if all of your IObject
implementations are reference types ( class
) not value types ( struct
). 如果所有
IObject
实现都是引用类型( class
)而不是值类型( struct
), 则不包括class
修饰符没有任何好处。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.