【问题标题】:Why we cannot assign an object directly to method which returns the same type?为什么我们不能将对象直接分配给返回相同类型的方法?
【发布时间】:2018-11-15 14:59:51
【问题描述】:

我是出于好奇而问这个问题,并且我知道其他方法。

我想知道,如果某个方法返回某种类型的对象,我们可以直接修改该对象的属性(即时 - 无需将其引用到局部变量中)。

为什么我们需要将它的引用引入局部变量来改变对象本身?

在编译器级别可能存在限制程序员这样做的逻辑困难。

参见下面的示例代码:

static Demo StaticDemoInstance;
static void Main(string[] args)
{
    //allowed: means I can directly modify property of static instance
    //  received from method
    GetDemo().Name = "UpdateDemo";

    //allowed: means I can get instance and overwrite it with other instance
    //      but not directly from method
    Demo d = GetDemo();
    d = new Demo("NewCreatedDemo", false);

    //not allowed: means I can't do second step directly on method
    //  question: 
    //      when I can update instance property without receiving instance on local variable
    //      what possible violation/difficulty (in compiler) will be there so it doesn't allow this
    GetDemo() = new Demo("UpdatedDemoFromGetMeth", false);
}

static Demo GetDemo() => StaticDemoInstance ?? 
                         StaticDemoInstance = new Demo("StaticDemo", false);

【问题讨论】:

  • GetDemo() = new Demo("UpdatedDemoFromGetMeth", false); 你是……没有分配属性……GetDemo() 是一种方法……当心投票者。
  • @BagusTesa 是的,我知道.. 我已经写了这个问题本身GetDemo().Name = "UpdateDemo"; 我正在设置属性
  • 好吧,您可以在下面看到@TheGeneral 的答案,但它仅适用于 C#7.0。我仍然坚持 5.
  • 您为什么要这样做,而不是仅仅将GetDemo() 设为可写的Demo 属性?
  • @BagusTesa 那么你不能......就这么简单:-) 请注意,即使使用ref,您也只能ref 使用局部变量或字段,而不是属性。所以它的用途有点有限。

标签: c# object methods reference


【解决方案1】:

你总是可以使用Ref return

从 C# 7.0 开始,C# 支持引用返回值(ref 返回)。引用返回值允许方法返回一个 引用一个变量,而不是一个值,返回给调用者。这 然后,调用者可以选择将返回的变量视为 通过值或引用返回。调用者可以创建一个新的 本身是对返回值的引用的变量,称为 参考本地。

限制

方法可以返回的表达式有一些限制 作为参考返回值。限制包括:

  • 返回值的生命周期必须超出方法的执行范围。换句话说,它不能是局部变量 在返回它的方法中。它可以是实例或静态字段 一个类,或者它可以是传递给方法的参数。尝试 返回局部变量会生成编译器错误 CS8168,“Cannot 通过引用返回本地 'obj',因为它不是本地 ref。”

  • 返回值不能是文字空值。返回 null 会生成编译器错误 CS8156,“无法在此使用表达式 上下文,因为它可能不会通过引用返回。”

  • 具有 ref 返回的方法可以将别名返回给当前值为空(未实例化)值或可为空类型的变量 对于值类型。

  • 返回值不能是常量、枚举成员、属性的按值返回值、类的方法或 结构。违反此规则会生成编译器错误 CS8156,“An 表达式不能在这种情况下使用,因为它可能不是 通过引用返回。”

一个真正人为的例子而不是我推荐的,但它确实实现了你的目标(学术上)

示例

static Demo StaticDemoInstance;

...

static ref Demo GetDemo()
{
   if (StaticDemoInstance == null)
      StaticDemoInstance = new Demo("StaticDemo", false);

   return ref StaticDemoInstance;
}

..

GetDemo() = new Demo("UpdatedDemoFromGetMeth", false);

更新

可以通过进一步复杂的示例和修改来看到它的使用

示例

static Demo Test()
{
   return StaticDemoInstance;
}

...

GetDemo() = new Demo("UpdatedDemoFromGetMeth", false);
var someObject = Test();
someObject= new Demo("Test", false);

Console.WriteLine(StaticDemoInstance.Name);
Console.WriteLine(someObject.Name);

输出

UpdatedDemoFromGetMeth
Test

Test 方法(不是 ref 返回)并且只给你一份引用的副本(因为缺乏更好的术语),如果你覆盖它,你的静态变量 StaticDemoInstance 不会改变

【讨论】:

  • 是的,我已经阅读了您之前的回答,这只会引发我的好奇心!如果 c# 7 已经引入了,那么这样做一定很有用!但是“为什么我们需要明确写 ref 而不能直接写”的问题让我很生气。
  • 看到你的更新后,我点击了投票按钮.. 发现我已经为你的第一篇文章做了这个.. 现在我需要加倍投票:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 2018-02-02
相关资源
最近更新 更多