大家好,我已经将某些复杂的需求移到了我需要了解的核心内容中。

我想将一个值的集合发送到一个方法,并且在该方法内部,我想针对一个实体的属性来测试该值。该属性将始终与值具有相同的类型。

我还想测试该值是否为null或默认值,显然取决于值类型是引用类型还是值类型。

现在,如果发送给该方法的所有值都属于同一类型,那么我可以很容易地使用泛型来做到这一点,如下所示:

public static void testGenerics<TValueType>(List<TValueType> Values) {

        //test null/default
        foreach (TValueType v in Values) {
            if (EqualityComparer<TValueType>.Default.Equals(v, default(TValueType))) {
                //value is null or default for its type
            } else {
                //comapre against another value of the same Type
                if (EqualityComparer<TValueType>.Default.Equals(v, SomeOtherValueOfTValueType)) {
                    //value equals
                } else {
                    //value doesn't equal
                }
            }
        }
    }


我的问题是,如果我的Collection包含不同类型的值,我将如何执行相同的功能。

我主要关心的是成功识别空值或默认值,并成功识别传入的每个值是否等于相同类型的其他值。

我可以通过简单地传递类型对象来实现吗?我也不能真正使用EqualityComparers,因为我不能使用泛型,因为我传入的是未知数量的不同类型。

有解决方案吗?

谢谢

更新

好的,四处搜寻,我可以使用以下代码在我的场景中成功测试null /默认值(取自this SO answer):

object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;


我认为这可能有效。

现在,如何在不成功且可靠地知道两个类型的情况下成功比较两个相同类型的值?

最佳答案

Object.Equals(object left, object right)静态方法,它内部依赖于提供的参数之一可用的Equals(object)实现。为什么要避免使用它?

实现平等成员的规则几乎如下:


必需:覆盖Equals(object)GetHashCode()方法
可选:为您的类型实现IEquatable<T>(这是EqualityComparer.Default所依赖的)
可选:实现==和!=运算符


因此,如您所见,如果您要依赖object.Equals(object left, object right),这将是依赖于平等实施模式强烈要求的部分的最佳解决方案。

而且,这将是最快的选择,因为它仅依赖于虚拟方法。否则,您无论如何都要进行反思。

public static void TestGenerics(IList values) {
  foreach (object v in values) {
    if (ReferenceEquals(null,v)) {
      // v is null reference
    }
    else {
      var type = v.GetType();
      if (type.IsValueType && Equals(v, Activator.CreateInstance(type))) {
        // v is default value of its value type
      }
      else {
        // v is non-null value of some reference type
      }
    }
  }
}

10-05 20:48
查看更多