如何在C#<6中模拟C#6空条件

使用C#6.0,我可以做到这一点

var isEqual = x.Id == y.Id && x.UpdatedAt == y.UpdatedAt && x.Name == y.Name && x.RulesUrl == y.RulesUrl && x.OngoingChallenges?.Count == y.OngoingChallenges?.Count && x.MembershipIds?.Count == y.MembershipIds?.Count; 

有没有什么好的解决方案,用C#<6.0做到这一点?

我的意思是这部分

 && x.OngoingChallenges?.Count == y.OngoingChallenges?.Count && x.MembershipIds?.Count == y.MembershipIds?.Count; 

因为在旧项目中我们没有可能使用C#6.0。 如何有效地写isEqual

x.OnGoingChallenges?.Count相当于x.OnGoingChallenges != null ? x.OnGoingChallenges.Count : default(int?) x.OnGoingChallenges != null ? x.OnGoingChallenges.Count : default(int?) (还有其他方法,但在一天结束时是空检查的快捷方式,称为空条件运算符 )。

也就是说,在没有C#6的情况下,您的代码无法使用语法优雅的语句进行重写,但您可以使用扩展方法模拟这个新的C#6function…

 public static class StructExtensions { // Check that TProperty is nullable for the return value (this is how C#6's // null-conditional operator works with value types public static TProperty? GetOrDefault(this TObject someObject, Func propertySelectionFunc) where TObject : class where TProperty : struct { Contract.Requires(propertySelectionFunc != null); return someObject == null ? default(TProperty?) : propertySelectionFunc(someObject); } } 

现在,您在C#5中的代码如下所示:

 var isEqual = x.Id == y.Id && x.UpdatedAt == y.UpdatedAt && x.Name == y.Name && x.RulesUrl == y.RulesUrl && x.OngoingChallenges.GetOrDefault(c => c.Count) == y.OngoingChallenges.GetOrDefault(c => c.Count) && x.MembershipIds.GetOrDefault(m => m.Count) == x.MembershipIds.GetOrDefault(m => m.Count); 

整个扩展方法可用于获取值类型属性值或其默认值。 您可能会也可能不会扩展扩展方法类,以支持获取引用类型值或null。

在C#version <6.0中,您将使用三元表达式

 var isEqual = x.Id == y.Id && x.UpdatedAt == y.UpdatedAt && x.Name == y.Name && x.RulesUrl == y.RulesUrl && (x.OngoingChallenges == null ? 0 : x.OngoingChallenges.Count) == (y.OngoingChallenges == null ? 0 : y.OngoingChallenges.Count) && (x.MembershipIds == null : 0 ? x.MembershipIds.Count) == (y.MembershipIds == null : 0 : y.MembershipIds.Count); 

正如@Hamlet Hakobyan指出的那样,这不是语义上完全相同的原始C#6.0解决方案使用?. ,但您可以将其更改为(根据@hvd):

 int? count = x.MembershipIds == null : default(int?) ? x.MembershipIds.Count; 

这取决于您是否要考虑缺少集合和空集合是否相等。


你也可以使用null合并运算符?? 并提供替换对象。 假设您的对象是某种类型的列表:

 var empty = new List(); var isEqual = x.Id == y.Id && x.UpdatedAt == y.UpdatedAt && x.Name == y.Name && x.RulesUrl == y.RulesUrl && (x.OngoingChallenges ?? empty).Count == (y.OngoingChallenges ?? empty).Count && (x.MembershipIds ?? empty).Count == (y.MembershipIds ?? empty).Count; 

在C#6之前,我使用过类似的东西

  public static class CommonExtensions { public static TValue TryGet(this TObject obj, Func getter, TValue defaultValue = default(TValue)) where TObject : class { return obj == null ? defaultValue : getter(obj); } //If objects types are equals public static bool KeyEquals(this TObject a, TObject b, Func keyGetter) where TObject : class { return a != null && b != null && EqualityComparer.Default.Equals(keyGetter(a), keyGetter(b)); } } var isEqual = x.Id == y.Id && x.UpdatedAt == y.UpdatedAt && x.Name == y.Name && x.RulesUrl == y.RulesUrl //v1 && x.OngoingChallenges.TryGet(v => v.Count) == y.OngoingChallenges.TryGet(v => v.Count) //v2 && x.MembershipIds.KeyEquals(y.MembershipIds, v => v.Count);