C# 通用比较方法 [C++模板的类似物]
C# generic compare method [analogue of C++ template]
C++和C#都支持泛型。但是,我没有看到任何方法可以重写一个简单的C++函数模板,该模板将任何两个参数(arg1> arg2 ?(进行比较为单个 C# 泛型方法:
C++
template<typename T>
int compare(const T & st1, const T & st2) {
if (std::less<T>() (st1, st2))
return -1;
return 1;
}
适用于int
、std::string
、std::vector
等。
compare(33, 4); // 1
std::vector<int> v1{ 1,0 }, v2{ 1,0,0 };
compare(v1, v2); // -1
std::vector<std::string> vs1{ "hi", "bob" }, vs2{ "hi", "ben" };
compare(vs1, vs2); // 1
C#
class Demo
{
public static int Compare<T>(T v1, T v2) where T : IComparable<T>
{
if (v1.CompareTo(v2) < 0)
return -1;
return 1;
}
}
不适用于,比如 C#Lists<>
:
List<int> v1 = new List<int> { 1, 2 };
List<int> v2 = new List<int> { 3, 4 };
Console.WriteLine($"Compare(v1, v2): {Compare(v1, v2)}");
错误:没有从"System.Collections.Generic.List"到"System.IComparable>">
的隐式引用转换是使其在 C# 中同时使用整型和集合以每次重载的唯一方法吗?
public static int Compare<T>(List<T> v1, List<T> v2) where T : IComparable<T>
{
for (int i = 0; i < v1.Count; i++)
{
if (v1[i].CompareTo(v2[i]) < 0)
return -1;
}
return 1;
}
错误的直接原因是List<int>
没有实现IComparer<List<int>>
并且这一事实不符合方法的规范:
public static int Compare<T>(T v1, T v2) where T : IComparable<T>
由于T
必须实施IComparable<T>
.
我建议这样的东西(快速,在某些情况下是一个肮脏的解决方案(:
public static int Compare<T>(T v1, T v2, IComparer<T> comparer = null) {
if (null == comparer) // If we don't have tailored comparer
comparer = Comparer<T>.Default; // Try default one
// If we don't know how to compare - throw exception
if (null == comparer)
throw new ArgumentNullException("comparer",
$"Type {typeof(T).Name} doesn't have default comparer; comparer must not be null.");
// Taken from the question:
// if (v1.CompareTo(v2) < 0)
// return -1;
// return 1;
// You, probably, may want just
// return comparer.Compare(v1, v2);
return comparer.Compare(v1, v2) < 0 ? -1 : 1;
}
所以你可以把,在一个简单的案例中
int result = Compare(15, 25); // Comparer<int>.Default will be used
在没有默认比较器的复杂情况下,您必须实现它:
public class MyComparer<T> : IComparer<IEnumerable<T>> {
public int Compare(IEnumerable<T> x, IEnumerable<T> y) {
if (Object.ReferenceEquals(x, y))
return 0;
else if (null == x)
return -1;
else if (null == y)
return 1;
Comparer<T> comparer = Comparer<T>.Default;
using (var en_x = x.GetEnumerator()) {
using (var en_y = y.GetEnumerator()) {
if (!en_x.MoveNext())
if (!en_y.MoveNext())
return 0;
else
return 1;
else if (en_y.MoveNext())
return -1;
if (comparer != null) {
int result = comparer.Compare(en_x.Current, en_y.Current);
if (result != 0)
return result;
}
}
}
return 0;
}
}
并提供比较器
List<int> v1 = new List<int> { 1, 2 };
List<int> v2 = new List<int> { 3, 4 };
int another result = Compare(v1, v2, new MyComparer<int>());
如果要比较相等性,可以使用EqualityComparer<T>.Default
,因为不能将泛型类型与==
进行比较(== null
除外(。
/// <returns>
/// <see langword="true" /> if <paramref name="v1" /> is equal to <paramref name="v2" />; otherwise, <see langword="false" />.
/// </returns>
public static bool Compare<T>(T v1, T v2)
{
return EqualityComparer<T>.Default.Equals(v1 , v2);
}
您可能需要详细说明要比较的内容,因为某些概念(例如大于,小于,项目计数等(对于任何任意T
都没有意义。
编辑:
似乎您想比较集合的项目。那么不限制T
成为IEnumerable
是没有意义的。
您可以使用Enumerable.SequenceEqual
来比较集合是否包含相同的项目,甚至可以为每个项目指定一个比较器。
当您编写以下内容时,您已将 T 定义为 IComparable 类型(或其后代(:
where T : IComparable<T>
在您的示例中,您使用 int 作为列表的类型,该列表的类型不是 IComparable 类型,因此抛出转换错误。
- 如何在c++中使用引用实现类似python的行为
- 使用Qt C++计算类似Git的SHA1哈希
- Visual Studio 中是否有来自代码块的编译器标志的类似物?
- C++合并类似物
- C# 通用比较方法 [C++模板的类似物]
- STD ::与指定线程的异步类似物
- QT有GSL :: Span的类似物吗?
- 用于嵌入式设备的轻巧SMBClient类似物
- C#扩展方法类似物在C 中
- Python方法的OpenCV C 类似物
- Pascal类型二进制文件的C++和Python类似物
- 整数输出格式.什么是 printf(%.3x) 的类似物
- C++中xmalloc的右类似物
- 除了函数之外,是否有对象的"this"的类似物?
- 不带GLkit的OpenGL ES.GLKMatrix和纯OpenGL ES中函数的类似物
- 与 Ruby's Rack 最接近C++类似物是什么?
- _mm_cvtsd_f64高阶浮点的类似物
- Altivec:_mm_sad_epu8()的类似物
- DirectX — 有没有类似 DirectDraw surface Flip() 的类似物
- c++中的strtok()类似物