C# 在C中安全地强制转换泛型类型#

C# 在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

如何根据给定的泛型类型安全地强制转换和返回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;
}
我的答覆是:

    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
was
null
,您希望
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);
}