簡體   English   中英

C# 引用類型(即“out”參數) typeof(char &) 或 typeof(out char)

[英]C# type of references (i,.e. "out" parameters) typeof(char &) or typeof(out char)

對於某些庫調試用途,我正在開發一個自定義屬性,該屬性應該能夠匹配現有方法。

例如以下:

[NetMethodAliasMethod("TryParse", Parameters = new Type[] { typeof(string), typeof(char)})]

...應該匹配 static bool System.Char.TryParse (string? s, out char result) 針對 ParameterInfo.ParameterType MethodInfo.GetParameters() 測試屬性“Parameters”以匹配參數(當然名稱也匹配)。

如果是string? 這是有效的,因為可空屬性不是類型的一部分。 但是,從MethodInfo返回的第二個參數的類型是char& ,而typeof(char&)是不允許的。 有沒有可能通過這種類型的方法?

我正在考慮泛型委托,但看不到任何方法,因為委托的使用要具體說明哪些方法是兼容的。 另一個想法是使用typeof(System.Char).GetMethod("TryParse") 但是,如果存在多個重載,這會導致同樣的麻煩,我們將不得不使用GetMethods (帶有 's'),並再次匹配參數類型。

當然,我可以使用類型名稱的字符串檢查,但如果沒有其他方法,那應該是最后的手段。 但是既然Type(char&)存在,我希望有辦法得到它嗎?

您可以使用MakeByRefType方法創建這樣的類型。

但是,您在編寫屬性時實際上不能調用此方法,因為typeof(int).MakeByRefType()類的東西不是屬性參數表達式(在本節的最底部定義)。

因此,我會 go 的解決方法是為您的屬性聲明一個附加參數,該參數編碼這些“by refs”的位置:

public bool[] ParametersAreByRef { get; set; }

然后做:

[NetMethodAliasMethod(
    "TryParse", 
    Parameters = new Type[] { typeof(string), typeof(char)}
    ParametersAreByRef = new bool[] { false, true })]

只有當您稍后檢索該屬性時,您才會使用MakeByRefType根據ParametersAreByRef中的值重新創建Type

var modifiedParameters = attribute.Parameters.Zip(
    attribute.ParametersAreByRef, (t, b) => b ? t.MakeByRefType() : t
).ToArray()

如果您不喜歡每次都為所有非按引用參數的方法傳遞ParametersAreByRef ,您可以將Parameters設置為位置參數(將其作為構造函數參數),然后您可以將ParametersAreByRef初始化為Parameters.Select(x => false).ToArray()默認情況下或構造函數中的類似內容。

正如 Jeroen Mostert 在評論中所建議的那樣,另一種解決方法是使用指針類型,因為它們在實際代碼中非常罕見,因此對按引用進行編碼:

Parameters = new Type[] { typeof(string), typeof(char*)}

當您檢索屬性實例時,檢查IsPointer並使用GetElementType

var modifiedParameters = attribute.Parameters.Select(
    x => x.IsPointer ? x.GetElementType().MakeByRefType() : x
).ToArray();

如果有支持字段,您也可以在Parameters設置器中執行此操作。

或者,制作您自己的虛擬ByRef<T>類型,以便可以注釋 by-ref-ness:

public abstract class ByRef<T> {}

…

Parameters = new Type[] { typeof(string), typeof(ByRef<char>)}

然后

// e.g. in the setter of Parameters
_parameters = Parameters.Select(
    x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ByRef<>) ? x.GetGenericArguments()[0].MakeByRefType() : x
).ToArray();

我喜歡@JeroenMostert 評論的優雅,所以我在我的屬性中添加了一個 ByRef 抽象通用 class :

public abstract class ByRef<T> { };

並修改了Parameters屬性來解析類型

private Type[]? _parameters = null;
public Type[]? Parameters
{
  get { return _parameters; }
  set
  {
    if(value==null)
    {
      _parameters = null;
      return;
    }

    for(int i=0; i<value.Length; i++)
    {
      Type type = value[i];

      if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ByRef<>))
      {
        value[i] = type.GetGenericArguments()[0].MakeByRefType();
      }

      _parameters = value;
    }
  }
}

此設置器將所有 ByRef 解析為 T&

請注意,在我的例子中, Parameters可以為空,因為我使用 null 作為參數通配符(即匹配任何類型和計數)。

暫無
暫無

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

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