繁体   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