簡體   English   中英

是否可以將泛型類型參數約束為String OR Array

[英]Is it possible to constrain a generic type parameter to String OR Array

簡而言之:是否可以定義一個泛型方法,其中類型參數( T )被約束為stringint[] 在偽C#中,我想要做的是:

public static int MyMethod<T> ( T arg1, T arg2 ) 
    where T : (has an indexer that returns an int) {
    // stuff with arg1[i], arg2[j], etc...
}

請注意,在C#中,由於內置string索引器(返回一個char )以及從charint隱式轉換,以下表達式意味着sourcestring還是int[]完全相同:

int someval = source[index];

根據線程將Constrain泛型擴展方法用於基類型和字符串我意識到我不能只在where T : x... constraint子句中創建一個無關聯類型的列表。 int[]string都符合T: IEnumerable<int> ,但IEnumerable<T>不要求實現者擁有索引器,這正是我在兩種類型中使用的常見功能。

這背后的目的是我正在構建一些高度優化的字符串解析和分析功能,例如Damerau-Levenshtein距離算法的快速實現。 我發現,首先將我的字符串轉換為int數組有時會在重復的逐字符處理中產生明顯更快的執行(與DL算法一樣)。 這主要是因為比較int值比比較char值要快得多。

操作詞是“有時”。 有時,直接在字符串上操作更快,並避免首次轉換和復制到int數組的成本。 所以我現在擁有除聲明之外真正相同的方法。

當然我可以使用dynamic ,但運行時檢查的性能損失完全破壞了方法構造中的任何收益。 (我做過測試)。

不,C#不允許您創建這樣的“復合”約束。

你展示的表達方式意味着同樣的事情,但你不能利用這個事實來發揮你的優勢。 C#泛型在語法上類似於C ++模板,但它們的工作方式完全不同,因此索引器執行相同操作的事實最終變得無關緊要。

當然,您可以使用您需要的特定類型創建兩個重載,但這確實意味着一些煩人的復制和粘貼。 任何試圖抽象以避免重復的嘗試都會使你的表現嚴重受損。

你不能有一個約束,說“類型必須有一個索引器”。

但是,您可以使用一個約束,指出“類型必須實現具有索引器的接口”。 例如,這樣的接口可能是IList<char>

不幸的是, string沒有實現IList<char> ,所以你必須為它編寫一個小的包裝類:

sealed class StringWrapper : IList<char>
{
    public string String { get; private set; }
    public StringWrapper(string str) { String = str; }
    public static implicit operator StringWrapper(string str)
    {
        return new StringWrapper(str);
    }

    public char this[int index]
    {
        get { return String[index]; }
        set { throw new NotSupportedException(); }
    }

    // Etc.... need to implement all the IList<char> methods
    // (just throw NotSupportedException except in the ones that are trivial)
}

然后你可以像這樣聲明你的方法:

public static TElement MyMethod<TCollection, TElement>(TCollection arg)
    where TCollection : IList<TElement>
{
    return arg[0];
}

[...]

MyMethod<StringWrapper, char>("abc")     // returns 'a'
MyMethod<int[], int>(new[] { 1, 2, 3 })  // returns 1

你可以讓你的方法簽名

public static int MyMethod<T> ( T[] arg1, T[] arg2 )

並在傳遞字符串參數之前使用String.ToCharArray()(或者在重載時,你得到了想法...)

暫無
暫無

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

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