代码之家  ›  专栏  ›  技术社区  ›  Amit

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

  •  1
  • Amit  · 技术社区  · 8 年前

    我问这个是出于好奇,我知道其他的方法。

    我想知道,如果某个方法返回某个类型的对象,我们可以直接修改该对象的属性(动态地-不将其引用带入局部变量)。

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

    在编译器级有哪些逻辑困难限制了程序员这样做。

    参见下面的示例代码:

    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);
    
    1 回复  |  直到 8 年前
        1
  •  6
  •   TheGeneral    8 年前

    你总是可以用 Ref return

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

    局限性

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

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

    • 返回值不能为文本null。返回null将生成编译器错误cs8156,“表达式不能用于 上下文,因为它可能无法通过引用返回。“

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

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

    做作的例子 不是我推荐的 ,但它确实实现了你的目标(学术上)

    例子

    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 return)并且只提供引用的副本(因为缺少更好的术语),如果覆盖它,静态变量将 StaticDemoInstance 不会改变的