0

我不明白为什么当传递的变量在堆上时跟踪引用没有完成它的工作。这是代码:

ref class DataContainer
    {
    public:
        property DateTime Time;
    };

DataContainer^ dc = gcnew DataContainer ();
DateTime timeOnStack;
// first call with output variable on the stack
bool timeParsed = DateTime::TryParseExact ("20160104132500184", "yyyyMMddHHmmssfff", CultureInfo::InvariantCulture, DateTimeStyles::None, timeOnStack);
// second call with output variable on the heap
timeParsed = DateTime::TryParseExact ("20160104132500184", "yyyyMMddHHmmssfff", CultureInfo::InvariantCulture, DateTimeStyles::None, (dc->Time));

第一个TryParseExact调用使用本地初始化变量timeOnStack来放置解析的 DateTime 值按预期工作并正确设置解析日期:调用timeOnStack.ToString ()返回"1/4/2016 1:25:00 PM" 而第二个调用即使返回true它也没有设置正确的值dc->Time:调用dc->Time.ToString ()返回"1/1/0001 12:00:00 AM"

我在这里没有看到什么?

4

1 回答 1

3

传递跟踪引用(ref在 C# 中)是传递对象的本地存储地址,而不是传递对象。但是,dc->Time在您的示例中,它不是局部变量或字段,而是属性。请记住,在底层,属性是 getter/setter 方法对。你在这里拥有的是等价于dc->GetTime().

编译器正在接受您的方法调用,并将该方法调用的结果作为跟踪参考传递。没有将其分配回财产;这不是它的工作原理。接收方法调用结果并作为跟踪引用传递的临时局部变量不可用。

如果你在 C# 中尝试这个,你会得到一个错误A property or indexer may not be passed as an out or ref parameter.C++/CLI 允许这个通过,尽管可能不是你想要的。

编译器可以选择实现一些语法糖:调用属性getter,分配给临时变量,然后调用setter。但是,C# 和 C++/CLI 都选择不实现它,原因很充分:看看为什么 C# 不提供内部帮助器来传递属性作为参考?.

于 2016-01-04T16:15:45.683 回答