Jos*_*nig 9 c# string generics
简而言之:是否可以定义一个泛型方法,其中类型参数(T
)被约束为string
或int[]
?在伪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...
}
Run Code Online (Sandbox Code Playgroud)
请注意,在C#中,由于内置string
索引器(返回a char
)以及从char
to的隐式转换 int
,以下表达式意味着完全相同的source
是a string
还是int[]
:
int someval = source[index];
Run Code Online (Sandbox Code Playgroud)
根据线程将Constrain泛型扩展方法用于基类型和字符串我意识到我不能只在where T : x...
约束子句中创建一个非关联类型的列表.双方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)
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样声明你的方法:
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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2521 次 |
最近记录: |