2016-01-12 38 views
5

我对C#相当陌生#dynamic关键字。在我的其中一个项目中,我尝试使用它,并遇到一些意外的行为。我设法再现与下面的代码的情况:动态不尊重退货类型

class Program 
{ 
    static DateTime? DateOnly(DateTime? time) 
    { 
     return time.HasValue ? (System.DateTime?)time.Value.Date : null; 
    } 

    static void Main(string[] args) 
    { 
     dynamic now = System.DateTime.Now; 
     var date = DateOnly(now); 
     Console.WriteLine(date.Value); // error thrown here 
     Console.Read(); 
    } 
} 

我得到一个RuntimeBinderException

“System.DateTime的”不包含“价值”的定义。

所以可变date被视为DateTime代替DateTime?

它看起来像dynamic某种程度上忽略返回类型声明。 我是否应该避免在dynamic处使用var

回答

5

因为你传递一个dynamic变量到DateOnly方法,返回类型也变得动态的。所以在这种情况下,您的var date实际上是dynamic date。它包含一个可空盒装DateTime,但拳击不保留“可空”的一部分,所以实际上它只是一个盒装DateTime,它不具有Value财产。所以你应该做Console.WriteLine(date)打印价值。

正如你所看到的,可空类型和dynamic不玩很好地结合在一起......

0

看看你的函数参数,你要求一个可为空的类型。 DateTime(System.DateTime.Now)是一个值类型,默认情况下,值类型不可为空。

+0

@PoweredByOrange可空是一个结构。 –

2

有两个问题。一个是date仍然是动态的,因为右侧是一个动态表达式。如果您已经声明date与特定类型DateTime?你不会看到这一点。另一个问题是,你正在返回一个可为空的值类型,并且转换为动态被认为是装箱。可为空的值类型从不像这样装箱。底层值类型已解包,因此date的行为更像是类型为object的参考,它可以具有DateTime或可以为null,而不是对DateTime?的引用。绑定器然后尝试根据DateTime解析属性Value并失败。如果您尝试Console.WriteLine(date),但它会失败,因为该方法有很多重载。所以你必须做一些类似于Console.WriteLine((object)date)的事情,在这一点上,你可以声明dateobject这个简单的例子。

+0

您的意思是“右手边”? –

+0

@ThomasLevesque是的,我的意思是另一个左边。固定。 –