簡體   English   中英

在C#中安全地轉換泛型類型

[英]Safely cast a Generic type in C#

如何根據給定的泛型類型安全地強制轉換並返回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;
}

我知道,如果相反,如果m_obj我有一個列表,我可以簡單地做到這一點:

private readonly IList<Object> m_objects;

internal IList<T> Collect<T>() where T : IObject
{
    return m_objects.OfType<T>().ToList();
}

但是我找不到以前的代碼的解決方案。

public interface IObject
{

}

我的答案:

    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;
    }

as關鍵字適用於引用類型。

編譯器不知道T確實是引用類型,因此它會向您喊叫並且不會編譯。
通過在IObject約束之前添加class約束 ,可以告訴編譯器它是引用類型。 現在您可以放心了。

as運算符保留用於引用類型。 如果T始終是引用類型,則解決方案是向TryGetAs<T>添加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;
    }
}

在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);
}

將與最終解決方案一樣,並且可能更快(因為空檢查比is檢查更快)。

如果所有IObject實現都是引用類型( class )而不是值類型( struct ), 則不包括class修飾符沒有任何好處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM