属性如何在C#中实际工作,例如DateTime.Today?

时间:2015-06-28 01:35:51

标签: c# datetime methods properties dayofweek

我刚刚使用 struct DateTime.Today 看到了一些代码段代码,我无法理解它的内部工作原理。这是具体的一行:

if (DateTime.Today.DayOfWeek == DayOfWeek.Monday)

使用转到定义F12 之后,我看到今天静态方法返回 一个DateTime对象,其中包含当前计算机中的日期信息。我想 Today方法可以作为构造函数包装器使用。我无法推断的(更像是猜测)是如何在不首先实例化今日结构的情况下访问属性DayOfWeek

有人可以解释一下这怎么可能?我唯一的猜测是,当VS将代码编译为 IL 时,可能会将此语法糖转换为:

if ( (DateTime.Today()).DayOfWeek == DayOfWeek.Monday )

也许这就像水一样干净,但我是C#新手,所以我无法理解。

提前致谢!

2 个答案:

答案 0 :(得分:2)

与您的问题相关,DateTime.TodayProperty类型的DateTime,因此DateTime.DayOfWeek Property与常规DateTime一样Properties } 结构体。

广义上讲Properties如何在C#中工作:在第一次近似中,为了更好地理解,您可能会认为Methods伪装成Today看起来像一个字段,因此,您对GetToday()作为某种假设的Properties方法的解释在逻辑上是接近的,但在学术上并不精确" (见@CalebB的评论)。

我建议您熟悉.NET DateTimehttps://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx)和Structure JavaDStream<Status> inputDStream = TwitterUtils.createStream(ctx, new OAuthAuthorization(builder.build()), filters); inputDStream.foreach(new Function2<JavaRDD<Status>,Time,Void>(){ @Override public Void call(JavaRDD<Status> status, Time time) throws Exception { List<Status> statuses=status.collect(); for(Status st:statuses){ System.out.println("STATUS:"+st.getText()+" user:"+st.getUser().getId()); //Process and store status somewhere } return null; }}); ctx.start(); ctx.awaitTermination(); } https://msdn.microsoft.com/en-us/libraRy/system.datetime.aspx

希望这可能会有所帮助。

答案 1 :(得分:1)

你是对的,欢迎来到properties的精彩世界。

DateTime.Today是一个属性,简而言之就是编译器生成的函数,它转换为DateTime.get_today()。 所以表达式实际上是

if ( (DateTime.get_today()).DayOfWeek == DayOfWeek.Monday )

示例:

public class Test
{
    private string _lastName = "LName";
    private string _firstName = "FName";
    public string Name { get{
        return _lastName + " " + _firstName;
    } }

    public string GetName()
    {
        return _lastName + " " + _firstName;
    }
}
class Program
{
    static void Main(string[] args)
    {
        var test = new Test();
        Console.WriteLine(test.Name);
        Console.WriteLine(DateTime.Today.DayOfWeek);
    }
}

已反编译GetName

.method public hidebysig instance string 
        GetName() cil managed
{
  // Code size       28 (0x1c)
  .maxstack  3
  .locals init ([0] string CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldfld      string ConsoleApplication1.Test::_lastName
  IL_0007:  ldstr      " "
  IL_000c:  ldarg.0
  IL_000d:  ldfld      string ConsoleApplication1.Test::_firstName
  IL_0012:  call       string [mscorlib]System.String::Concat(string,
                                                              string,
                                                              string)
  IL_0017:  stloc.0
  IL_0018:  br.s       IL_001a
  IL_001a:  ldloc.0
  IL_001b:  ret
} // end of method Test::GetName

已反编译Name

.method public hidebysig specialname instance string 
        get_Name() cil managed
{
  // Code size       28 (0x1c)
  .maxstack  3
  .locals init ([0] string CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldfld      string ConsoleApplication1.Test::_lastName
  IL_0007:  ldstr      " "
  IL_000c:  ldarg.0
  IL_000d:  ldfld      string ConsoleApplication1.Test::_firstName
  IL_0012:  call       string [mscorlib]System.String::Concat(string,
                                                              string,
                                                              string)
  IL_0017:  stloc.0
  IL_0018:  br.s       IL_001a
  IL_001a:  ldloc.0
  IL_001b:  ret
} // end of method Test::get_Name

反编译Main(方法调用)

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       56 (0x38)
  .maxstack  1
  .locals init ([0] class ConsoleApplication1.Test test,
           [1] valuetype [mscorlib]System.DateTime CS$0$0000)
  IL_0000:  nop
  IL_0001:  newobj     instance void ConsoleApplication1.Test::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  callvirt   instance string ConsoleApplication1.Test::get_Name() //here
  IL_000d:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0012:  nop
  IL_0013:  ldloc.0
  IL_0014:  callvirt   instance string ConsoleApplication1.Test::GetName()//here
  IL_0019:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_001e:  nop
  IL_001f:  call       valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Today()//here
  IL_0024:  stloc.1
  IL_0025:  ldloca.s   CS$0$0000
  IL_0027:  call       instance valuetype [mscorlib]System.DayOfWeek [mscorlib]System.DateTime::get_DayOfWeek()
  IL_002c:  box        [mscorlib]System.DayOfWeek
  IL_0031:  call       void [mscorlib]System.Console::WriteLine(object)
  IL_0036:  nop
  IL_0037:  ret
} // end of method Program::Main

正如您所看到的,NameGetName之间完全没有区别,除了编译器为您Name生成get_Name这一事实。

更新1

至于DateTime.Today它实际上已转化为

System.DateTime [mscorlib]System.DateTime::get_Today()

你必须要了解的是,即使编译器为你生成这些函数,它们也无法直接访问,因为它生成IL代码(.NET的汇编代码)而不是C#(事情可能已经改变了Roslyn的新功能) C#编译器,但对此知之甚少)

我建议,如果您对应用程序中真正发生的事情感到好奇,那就是使用ildasm.exe它可以让您看到编译器生成的IL。一本关于这个主题的好书,它通过C#称为CLR,我接触过第3版,但显然现在有第4版。