簡體   English   中英

如何檢查是否使用可為空的泛型參數調用泛型函數

[英]How to check if generic function is called with nullable generic argument

我正在嘗試編寫一個泛型函數,該函數的行為取決於是否使用允許空值的參數調用它。 在 C#8 之前的世界中,我使用的是這樣的東西:

T MyFunc<T>()
{
  object value = SomeExternalFunctionCall();
  if (value == null)
  {
    if (typeof(T).AcceptsNulls())
    {
      return null;
    }
    else
    {
      throw new Exception($"{typeof(T).Name} does not support nulls");
    }
  }
  return (T)value;
}

其中AcceptsNulls()是這樣的:

public static bool IsAcceptNulls(this Type type)
{
  if (type.IsValueType)
  {
    if (Nullable.GetUnderlyingType(type) != null)
    {
      return true;
    }
    return false;
  }
  return true;
}

因此, MyFunc對引用類型和值類型都能很好地工作,並適當支持可為空值類型。

但現在我想將它放在一個啟用可空引用類型的代碼中。 而且我希望它能夠區分MyFunc<object>()MyFunc<object?>()情況,因此在前一種情況下處理空值時會拋出,但在后一種情況下不會。

很明顯,我無法通過類型檢查來檢查這一點,因為引用類型可為空性是一個編譯時功能。

我怎么能這樣做? 有可能嗎?


更新

似乎我的意圖不清楚,所以我會更詳細地介紹。

我有一些產生值的代碼。 有時它可能會產生空值。 我想讓我的代碼用戶能夠決定他是否想從我的代碼中獲取空值。

對於可為空的結構,它確實可以正常工作:


int noNullsForThisVariable = MyFunc<int>();

int? nullsAreOkHere = MyFunc<int?>();

我現在想為引用類型提供相同的行為。

可能有誤會。

不可為空的引用類型,例如字符串(而不是字符串?)僅在設計時存在。 在運行時字符串是可以為空的,不管你是不是只寫了 string 而不是 string?。 弄清楚了這一點,問題就可以得到解答。 在可空性方面,c# 8 沒有任何改變。

讓我解釋一下為什么您的方法根本不適用於引用類型。 (至少在 c# 8 之前。這種行為可能會在未來的 c# 版本中改變)

因為引用類型在運行時總是可以為空的,所以 Type 本身沒有區別。

這可能就是你不能這樣做的原因: typeof(string?) 你會得到一個錯誤,比如:“typeof cannot be used for nullable reference types”

但這並不一定意味着編譯不會添加可區分的屬性或類似的東西。 (確實可能是)

但是我們可以說,如果兩種類型的字符串的 GetType() 都會產生相同的類型實例,那么這根本不可能是不同的類型。

使用以下代碼自行檢查。

    string nonNullableString = "3434";
    string? nullableString = "3434";

    var nnStringType = nonNullableString.GetType();
    var stringType = nullableString.GetType();

    var isEqual = nnStringType == stringType; // true
    if(object.ReferenceEquals(nnStringType, stringType)) // true
        Debug.Print("it's the same object");

可為空和不可為空的字符串屬於同一類型。

暫無
暫無

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

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