C# 在C中安全地强制转换泛型类型#
如何根据给定的泛型类型安全地强制转换和返回m_objC# 在C中安全地强制转换泛型类型#,c#,generics,casting,oftype,C#,Generics,Casting,Oftype,如何根据给定的泛型类型安全地强制转换和返回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 n
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;
}
我的答覆是:
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;
}
public bool TryGetAs(out T value),其中T:ioobject
{
值=默认值(T);
如果(!(m_obj是T))
返回false;
值=(T)m_obj;
返回true;
}
关键字适用于引用类型
编译器不知道t
确实是一个引用类型,因此它会向您喊叫并且不会编译。通过在
ioobject
约束之前添加,可以告诉编译器它是引用类型。现在您可以安全地进行强制转换。将as
操作符保留给引用类型。如果T
始终是引用类型,则解决方案是向TryGetAs
添加class
约束。如果T
也可以是值类型,则这不是选项。在这种情况下,您可以使用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;
}
}
public bool TryGetAs(out T value),其中T:class,ioobject
{
值=m_obj作为T;
返回值(值!=null);
}
将与最终解决方案的作用相同,并且可能更快(因为空检查比is
检查快)
如果所有的
IObject
实现都是引用类型(class
)而不是值类型(struct
),not包括class
修饰符没有任何好处。@mjwills编辑了这个问题。如果您有公共结构Bob:IObject{}
和m_obj
wasnull
,您希望TryGetAs
将值设置为什么?感谢IR,您能帮助我理解为什么.OfType()似乎可以安全地强制转换,尽管我们在这里再次处理IOObject<类型的code>使用is
而不是as
@mjwills这正是我的意思!尽管我们不知道IOObject是一个类或结构,但在上述代码中编译器不允许它。因为is
不需要引用类型as
需要它,因为它的行为是空的:D你不明白我的意思!我用正确的答案编辑了这个问题。谢谢Sefe,这正是我的意思。我发现它的时候,你张贴,我会标记它作为一个答案,虽然,你的问题是,你不认为T不能是一个类。甚至双结构在C ^实现,例如ICMePrimable。如果你小心行事,你会没事的。
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;
}
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;
}
}
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);
}