C# 使用键选择器和比较器进行单元测试
我将如何对这段LINQ代码进行单元测试C# 使用键选择器和比较器进行单元测试,c#,linq,unit-testing,C#,Linq,Unit Testing,我将如何对这段LINQ代码进行单元测试 public static IEnumerable<T> Distinct<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keySelector, IEqualityComparer<TKey> comparer) { return items.Distinct(new KeyEqualityComparer<T, TKey>
public static IEnumerable<T> Distinct<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
return items.Distinct(new KeyEqualityComparer<T, TKey>(keySelector, comparer.Equals));
}
公共静态IEnumerable Distinct(此IEnumerable项、Func键选择器、IEqualityComparer比较器)
{
返回items.Distinct(新的KeyEqualityComparer(keySelector,comparer.Equals));
}
我不知道最后如何使用比较器,这个的正确用法是什么
编辑:抱歉不清楚
我想知道的是:
class KeyEqualityComparer<T, TResult>: IEqualityComparer<T>
{
private readonly Func<T, TResult> _KeySelector;
private readonly Func<TResult, TResult, bool> _Predicate;
public KeyEqualityComparer(Func<T, TResult> keySelector, Func<TResult, TResult, bool> predicate)
{
if (keySelector == null)
throw new ArgumentNullException("keySelector");
_KeySelector = keySelector;
_Predicate = predicate ?? System.Collections.Generic.EqualityComparer<TResult>.Default.Equals;
}
public bool Equals(T x, T y)
{
return _Predicate(_KeySelector(x), _KeySelector(y));
}
public int GetHashCode(T obj)
{
// Always return the same value to force the call to IEqualityComparer<T>.Equals
return 0;
}
}
class KeyEqualityComparer:IEqualityComparer
{
专用只读功能键选择器;
私有只读Func_谓词;
公钥EqualityComparer(Func键选择器,Func谓词)
{
if(keySelector==null)
抛出新ArgumentNullException(“KeySelect”);
_键选择器=键选择器;
_谓词=谓词??System.Collections.Generic.EqualityComparer.Default.Equals;
}
公共布尔等于(TX,TY)
{
返回_谓词(_键选择器(x),_键选择器(y));
}
公共int GetHashCode(T obj)
{
//始终返回相同的值以强制调用IEqualityComparer.Equals
返回0;
}
}
此代码尝试执行与MoreLINQ的方法类似的操作,但不尽相同
基本上,这个想法是,给定一组项,您希望找到一组不同的项,但通过比较某个键的概念来专门测试其差异性。例如,您可能有一个Person
类型,如下所示:
// TODO: Use C# 6 primary constructor and read-only autoprops :)
public class Person
{
public string Name { get; set; }
public string Hobby { get; set; }
public string Profession { get; set; }
}
var people = new List<Person>
{
new Person { Name="Tom", Hobby="Minecraft", Profession = "Student" },
new Person { Name="Robin", Hobby="Taunting", Profession = "Outlaw" },
new Person { Name="Robin", Hobby="Angry Birds", Profession = "Student" },
};
有这样的数据:
// TODO: Use C# 6 primary constructor and read-only autoprops :)
public class Person
{
public string Name { get; set; }
public string Hobby { get; set; }
public string Profession { get; set; }
}
var people = new List<Person>
{
new Person { Name="Tom", Hobby="Minecraft", Profession = "Student" },
new Person { Name="Robin", Hobby="Taunting", Profession = "Outlaw" },
new Person { Name="Robin", Hobby="Angry Birds", Profession = "Student" },
};
var people=新列表
{
新人{Name=“Tom”,Hobby=“Minecraft”,Profession=“Student”},
新人{Name=“罗宾”,Hobby=“嘲弄”,Profession=“歹徒”},
新人{Name=“罗宾”,Hobby=“愤怒的小鸟”,Profession=“学生”},
};
现在,我们可以通过名字(在这种情况下,我们会得到汤姆和一只知更鸟)或职业(在这种情况下,我们会得到一个歹徒和一个学生)得到一组不同的人。我们可以另外指定一个相等比较器,以便在比较键时使用,例如,“TOM”和“TOM”可以被视为相等
LINQ中的Distinct
方法已经允许您指定自定义相等比较器,因此您的Distinct
方法(顺便说一句,我不会重载)只是将项投影到它们的键,并使用给定的键相等比较器来比较这些键
不幸的是,问题中给出的实现是糟糕的:一个IEqualityComparer
必须提供两种方法:一种是比较两个项目是否相等(这是正确的),另一种是获取哈希代码(这是非常糟糕的-它“有效”但效率极低)。基本上,通过执行比实际需要多得多的比较,将O(N)算法更改为O(N^2)算法
在单元测试方面,您可以使用我上面给出的示例:
- 按名称获取一个不同的集合
- 按职业分类
- 使用不区分大小写的相等比较器按名称获取不同的集合
或者您可以查看我的Morelink测试:)您的问题不清楚是代码做什么,应该如何使用它,还是应该如何进行单元测试……您是对的,我应该更清楚。我真的很想知道你问的所有问题。我相应地改变了我的问题。
KeyEqualityComparer
来自哪里(以及这段代码的其余部分)?(目前感觉不太可能正常工作,原因我只想在看到代码时解释。)我添加了KeyEqualityComparer的代码。这不是我的代码,我只是一个编程初学者,所以请原谅我是这样一个新手:)。提前感谢您的帮助!哎呀,这太糟糕了——考虑到GetHashCode的实现,这不是一个好的代码来研究,依我看。你能改变它吗?