为什么我们不能直接将对象分配给返回相同类型的方法?

Ami*_*mit 1 c# methods reference object

我出于好奇而问这个,我知道其他方法.

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

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

在编译器级别存在哪些逻辑上的困难会限制程序员这样做.

请参阅以下示例代码:

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);
Run Code Online (Sandbox Code Playgroud)

AAA*_*ddd 6

您总是可以使用Ref返回

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

限制

表达式有一些限制,方法可以作为引用返回值返回.限制包括:

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

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

  • 具有ref return的方法可以将别名返回到其值当前为null(未实例化)值的变量或值类型的可空类型.

  • 返回值不能是常量,枚举成员,属性的按值返回值,或类或结构的方法.违反此规则会生成编译器错误CS8156,"表达式不能在此上下文中使用,因为它可能不会通过引用返回."

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

static Demo StaticDemoInstance;

...

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

   return ref StaticDemoInstance;
}

..

GetDemo() = new Demo("UpdatedDemoFromGetMeth", false);
Run Code Online (Sandbox Code Playgroud)

更新

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

〔实施例

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);
Run Code Online (Sandbox Code Playgroud)

产量

UpdatedDemoFromGetMeth
Test
Run Code Online (Sandbox Code Playgroud)

Test方法(不是裁判的回报),并只给你参考(因为缺乏更好的术语)的副本,如果你覆盖它,你的静态变量StaticDemoInstance不改变