C# 链接以清理比较
每次我需要在C#中编写一个C# 链接以清理比较,c#,C#,每次我需要在C#中编写一个CompareTo方法时,我讨厌这样一个事实,即我不能像JavaScript中那样链接测试和结果: function int compareTo(a, b) { return a.Value1 - b.Value1 || a.Value2 - b.Value2 || a.Value3 - b.Value3; } 相反,在C#中,这看起来像: int CompareTo(object obj) { var other = obj as MyClass;
CompareTo
方法时,我讨厌这样一个事实,即我不能像JavaScript中那样链接测试和结果:
function int compareTo(a, b) {
return a.Value1 - b.Value1 || a.Value2 - b.Value2 || a.Value3 - b.Value3;
}
相反,在C#中,这看起来像:
int CompareTo(object obj)
{
var other = obj as MyClass;
if (other == null)
return 0;
int result = Value1 - other.Value1;
if (result != 0)
return result;
result = Value2 - other.Value2;
if (result != 0)
return result;
return Value3 - other.Value3;
}
有没有办法写出上面的“清洁剂”?它不必像JavaScript中那样是一行,但应该更具可读性且不易出错。使用通用扩展方法
NullableCompareTo
我们现在可以利用重构CompareTo
方法:
int CompareTo(object obj)
{
var other = obj as MyClass;
if (other == null)
return 0;
return Value1.NullableCompareTo(other.Value1)
?? Value2.NullableCompareTo(other.Value2)
?? Value3.CompareTo(other.Value3);
}
扩展方法
public static class ComparableExtensions
{
/// <summary>
/// Same as CompareTo but returns null instead of 0 if both items are equal.
/// </summary>
/// <typeparam name="T">IComparable type.</typeparam>
/// <param name="this">This instance.</param>
/// <param name="other">The other instance.</param>
/// <returns>Lexical relation between this and the other instance or null if both are equal.</returns>
public static int? NullableCompareTo<T>(this T @this, T other) where T : IComparable
{
var result = @this.CompareTo(other);
return result != 0 ? result : (int?)null;
}
}
公共静态类CompariableExtensions
{
///
///与CompareTo相同,但如果两项相等,则返回null而不是0。
///
///i可比较类型。
///这个例子。
///另一个例子。
///此实例与其他实例之间的词法关系,如果两者相等,则为null。
公共静态int?NullableCompareTo(this T@this,T other),其中T:IComparable
{
var result=@this.CompareTo(其他);
返回结果!=0?结果:(int?)null;
}
}
您可以使用扩展方法来模拟??
public static class Extensions {
public static T Coalesce<T>( this T self, T valueIfDefault ) {
return self.Equals( default(T) ) ? valueIfDefault : self;
}
}
如果单个比较比较比较昂贵,您还可以添加:
public static T Coalesce<T>( this T self, Func<T> valueIfDefault ) {
return self.Equals( default(T) ) ? valueIfDefault() : self;
}
public static T Coalesce(此T self,Func valueIfDefault){
返回self.Equals(默认值(T))?valueIfDefault():self;
}
这将被称为像
(Value1-other.Value1).合并(()=>比较昂贵(Value2,other.Value2)).合并(Value3-other.Value3)
,我个人讨厌像
这样的名字,而且它实际上不是一行。而且,原来的版本更干净(发生的事情更明显)。这个解决方案更快还是更好?@Sinatr它在我的代码中被称为test
,但为了答案的可读性,它改为。
。如果你能想出一个更干净的版本,请share@Xaruth不,那叫分享。顺便说一句,我希望我的答案不是最好的答案,有人会想出一个更语言集成的解决方案。这就是重点。你问题中的代码就是我的答案。已经很好了。我希望能分享一些好的东西。使用lambda和?
运算符来替换多个if
和null检查(如果它们没有好处)并不是很好。我没看见他们。它应该更慢,更不明显。那么,是什么让这个解决方案更好呢?我问题中的代码显然可读性较差,更容易出错。它只显示了3种情况,但有时你有10多种情况下,事情很容易出错。这个解决方案的问题是,你要事先评估每个值。这就是为什么我使用lambda函数,下一个值只在前面等于0的情况下被评估,它们是<代码> int /代码>减法,所以我不认为这是一个显著的缺点。你的答案有额外的分支;在我的测试代码中有6对2,即2n对n-1,在后空测试代码中。如果没有基准测试,这些额外的分支机构似乎至少也会对性能产生负面影响。无论如何,问题中冗长的方法可能比两者都快。还有,你对我的答案投了反对票吗?我扩展了我的答案以涵盖这种情况。它们是int
减法,因为我简化了这个问题,在我的代码中,它们是一些string.Compare()
调用,因此改变了情况。
public static T Coalesce<T>( this T self, Func<T> valueIfDefault ) {
return self.Equals( default(T) ) ? valueIfDefault() : self;
}