简体   繁体   English

比较类型,如果一个可以为空

[英]Compare types if one is nullable

I need to check if two types are the same: 我需要检查两种类型是否相同:

private bool AreOfTheSameType(object obj1, object obj2) {
  return obj1.GetType()==obj2.GetType();
}

This works fine with this values: 这适用于此值:

var test1=AreOfTheSameType(new DateTime(), new DateTime()) // true;
var test2=AreOfTheSameType(new int(), new DateTime()) // false;

What I now want is that the following returns true, too: 我现在想要的是以下也返回true:

var test3=AreOfTheSameType(new int?(), new int()) 

So if the types have the same base, but one is nullable, the other isn't, I also want to return it as true. 因此,如果类型具有相同的基础,但是一个可以为空,另一个不是,我也想将其返回为真。 Or to say it in another way I want to have a function that returns whether I can store obj1 into obj2 directly using reflection without having to cast the value. 或者以另一种方式说我希望有一个函数返回我是否可以直接使用反射将obj1存储到obj2而不必转换值。

UPDATE UPDATE

I reduced my code to make it more readable. 我减少了我的代码,使其更具可读性。 Looks like this time that was contra-productive. 看起来这次是反作用的。 The real-world-code follows: 真实世界代码如下:

var entity = Activator.CreateInstance(typeof(T));
Type entityType = typeof(T);
PropertyInfo[] entityProperties = entityType.GetProperties();
foreach (KeyValuePair<string, object> fieldValue in item.FieldValues)
{
   if (fieldValue.Value == null) continue;
   var property = entityProperties.FirstOrDefault(prop => prop.Name == fieldValue.Key);
   if (property != null && property.CanWrite)
   {
      Type valueType = fieldValue.Value.GetType();
      if (fieldValue.Value.GetType() == property.PropertyType) {
        // Assign
      }
   }
}

The problem on the "//Assign" - line is, I have the following two types: “// Assign”行上的问题是,我有以下两种类型:

fieldValue.Value.GetType().ToString()="System.DateTime"
property.PropertyType.ToString()="System.Nullable`1[System.DateTime]"

which are obiously not the same but could be assigned 虽然不一样但可以分配

which are obiously not the same but could be assigned 虽然不一样但可以分配

It looks like you're after the Type.IsAssignableFrom method: 看起来你在Type.IsAssignableFrom方法之后:

var dt = typeof(DateTime);            
var nd = typeof(DateTime?);

Console.WriteLine(dt.IsAssignableFrom(nd)); // false
Console.WriteLine(nd.IsAssignableFrom(dt)); //true

Live example: http://rextester.com/KDOW15238 实例: http//rextester.com/KDOW15238

Calling GetType on nullable types returns the original type: 在可空类型上调用GetType返回原始类型:

int? i = 5;  
Type t = i.GetType();  
Console.WriteLine(t.FullName); //"System.Int32"  

So AreOfTheSameType((int?)5, 5) should return true . 所以AreOfTheSameType((int?)5, 5)应该返回true

But as soon as you box a Nullable<T> , you either get null (if Nullable<T>.HasValue was false ), or you get the boxed underlying value, losing the "nullable" part. 但是只要你打开一个Nullable<T> ,你就会得到null (如果Nullable<T>.HasValuefalse ),或者你获得了盒装底层值,失去了“可空”部分。 So the problem you're facing here is that new int? 所以你在这里遇到的问题是new int? will be boxed into a null object when passed to the method. 传递给方法时将被装入一个null对象。

The problem with nullable types is that empty values box to null , and once they're null , you cannot find out what they were. 可空类型的问题是将空值框设置为null ,一旦它们为null就无法找出它们是什么。 The only way to solve this, then, is with generics: 那么解决这个问题的唯一方法是使用泛型:

private bool AreOfTheSameType<T1,T2>(T1 obj1, T2 obj2) {
  // get the types as best we can determine
  var t1 = obj1?.GetType() ?? typeof(T1);
  var t2 = obj2?.GetType() ?? typeof(T2);

  // Nullable<T> => T
  t1 = Nullable.GetUnderlyingType(t1) ?? t1;
  t2 = Nullable.GetUnderlyingType(t2) ?? t2;

  // compare
  return t1 == t2;
}

This will use the object if available (to allow for subclasses etc), but will fall back to typeof if the object is null - which means it should work for int? 这将使用对象( 如果可用) (允许子类等),但如果对象为null将返回typeof - 这意味着它应该适用于int? etc... as long as the type of the expression being passed in wasn't object to begin with; 等等...... 只要传入的表达式的类型不是开头的object ; if it was object and the value is null , then... you're out of luck - you can't ever find out the original type. 如果它 object并且值为null ,那么......你运气不好 - 你无法找到原始类型。 By which I mean: 我的意思是:

This should be fine: 这应该没问题:

var test3=AreOfTheSameType(new int?(), new int());

But this will fail: 但这会失败:

object x = new int?(), y = new int();
var test4=AreOfTheSameType(x, y);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM