开发者

Parameter converted from null to DateTime.MinValue when called using Invoke in C# 2.0

开发者 https://www.devze.com 2022-12-13 23:53 出处:网络
I have code a bit like this public class MyObject { private bool IsValidDay(ref DateTime theDate) { ... } } MethodInfo[] methods = myObjectInstance.GetType().GetMethod(\"IsValidDay\", BindingFlags

I have code a bit like this

public class MyObject
{
    private bool IsValidDay(ref DateTime theDate)
    {

    ...
    }
}


MethodInfo[] methods = myObjectInstance.GetType().GetMethod("IsValidDay", BindingFlags.Instance | BindingFlags.NonPublic);
object[] args = { null };
bool val = (bool)method.Invoke(myObjectInstance, args);

But when the method is called, from within the IsValidDay method, theDate is DateTime.MinValue. This seems awfully weird - I'd perhaps expect a NullReferenceException to be thrown but not an automatic conversion.

In case you are wondering, this is code in a unit test. (in use the method is typically called via a public method that takes object).

As far as some other code which 开发者_如何学Pythonis subsequently called is concerned, DateTime.MinValue and null are not the same thing, so it's a little bit of a problem.

Any clues?? Suggestions.


From MSDN:

Any object in this array that is not explicitly initialized with a value will contain the default value for that object type. For reference-type elements, this value is null. For value-type elements, this value is 0, 0.0, or false, depending on the specific element type.

The default value of DateTime is DateTime.MinValue:

DateTime.MinValue == new DateTime() // true

This explains why DateTime.MinValue gets passed to the method when you call it with null.

Note that you cannot pass null to the method anyway when you call it without reflection:

DateTime dt = null; // cannot assign null to value type
obj.IsValidDay(ref dt);

So I'd say you don't need to test your method with a null reference.


If you want your method to accept null, you can change the declaration to DateTime? as others have already pointed out:

private bool IsValidDay(ref DateTime? dt) { ... }


A DateTime variable can't be null. It's not a reference type, so there won't be a null reference exception.

You could do:

private bool IsValidDay(ref DateTime? theDate)
{
   if(theDate.HasValue)...
}

Here's a link talking about nullable types: http://msdn.microsoft.com/en-us/library/1t3y8s4s%28VS.80%29.aspx

I think I get what you are asking.... in the case of your code (especially because of the ref parameter, you can't have variance on a parameter with ref or out). It has to pass in a DateTime object. It can't be anything else.....so the null argument has to be converted to something to get the function to work.


DateTime has a value, I suggest you use DateTime? (or Nullable<DataTime>) to support nulls


Invoke() method takes an array of values for the target method parameters. According to MSDN, uninitialized elements of this array corresponding to the ref parameters will be initialized with the default value (in this case DateTime.MinValue) before the target method call.

Also, the value in the parameters array corresponding to the ref parameter will be updated after the target method call.

In your case you shouldn't test the method with a null value because it's not a valid value for the DateTime data type.

This is a comment from Invoke method doc in MSDN library:

"If the method or constructor represented by this instance takes a ref parameter, no special attribute is required for that parameter in order to invoke the method or constructor using this function. Any object in this array that is not explicitly initialized with a value will contain the default value for that object type. For reference-type elements, this value is null. For value-type elements, this value is 0, 0.0, or false, depending on the specific element type."

Also found this tutorial: Passing "ref" Parameters


Only reference types can be null. DateTime (like int, bool, structs, and enums) is a Value Type. Therefore DateTime cannot be null, just like an enum can't be null. You can use the Nullable generic, by declaring it as DateTime?. This will allow you to check it for null.


In the end, in this case, I think I'll go with the notion that the method doesn't actually need to be tested vs null, and note to myself that invoking methods via reflection doesn't always throw an exception when a straight function call would.

Other people may find the nullable type suggestion useful (though I imagine everybody has conttoned onto these by now...)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号