【问题标题】:C# assign by referenceC# 引用赋值
【发布时间】:2023-04-06 10:29:01
【问题描述】:

是否可以通过引用分配?我知道 ref 必须在方法中使用。

string A = "abc";
string B = A;
B = "abcd";
Console.WriteLine(A); // abc
Console.WriteLine(B); // abcd

可以给我一些吗

string A = "abc";
string B = (ref)A;
B = "abcd"; // A was assigned to B as reference, so changing B is the same as changing A
Console.WriteLine(A); // abcd
Console.WriteLine(B); // abcd

【问题讨论】:

标签: c#


【解决方案1】:

这就是它的工作原理。字符串是一种引用类型——您的变量 A 是对堆上字符串的引用(如指针),而您只是将指针的值(字符串的地址)复制到变量 B 中。

当您将“abcd”分配给 B 时,您的示例不会更改 A 的值,因为字符串在 .net 中被特殊处理。正如 Kevin 指出的那样,它们是不可变的,但同样重要的是要注意它们具有值类型语义,即赋值总是导致引用指向新字符串,并且不会更改存储在变量。

如果您使用(例如)汽车而不是字符串,并更改了属性,您会看到这种情况:

public class Car {
    public String Color { get; set; }
}

Car A = new Car { Color = "Red" };
Car B = A;
B.Color = "Blue";
Console.WriteLine(A.Color); // Prints "Blue"

// What you are doing with the strings in your example is the equivalent of:
Car C = A;
C = new Car { Color = "Black" };

可能值得注意的是,它不适用于值类型(整数、双精度、浮点数、长整数、小数、布尔值、结构等)。这些是按值复制的,除非它们被装箱为Object

【讨论】:

  • 善用“等价”示例——更容易理解。
【解决方案2】:

您没有修改对 A 的引用。您正在创建一个全新的字符串。 A仍然显示“abc”,因为它不能通过修改B来改变。一旦修改B,它就指向一个全新的对象。字符串也是不可变的,因此对字符串的任何更改都会创建一个新字符串。

为了进一步回答您关于非不可变引用类型的问题,可以修改变量指向的对象的属性,当您访问指向同一对象的其他变量时,它将显示更改后的效果。然而,这并不意味着您可以让一个变量指向一个全新的对象,而让其他变量(指向旧对象)自动指向该新对象而无需修改它们。

【讨论】:

  • 这不是真的。他只是更改了B 变量的引用。如果 b 是 List<int> 类型,那也是同样的事情。
  • 是的,我写得太快了。我认为这使它更清晰一些。
【解决方案3】:

字符串是不可变的,这是真的。但是,您可以通过将字符串封装在一个类中并创建该类的 A 和 B 实例来解决您的问题。那么 A = B 应该可以工作。

【讨论】:

    【解决方案4】:
    public class ReferenceContainer<T>
    {
         public T Value {get;set;}
         public ReferenceContainer(T item)
         {
             Value = item;
         }
    
         public override string ToString()
         {
            return Value.ToString();
         }
    
         public static implicit operator T (ReferenceContainer<T> item)
         {
             return Value;
         }
    }
    
    var A = new ReferenceContainer<string>("X");
    var B = A;
    B.Value = "Y";
    Console.WriteLine(A);// ----> Y
    Console.WriteLine(B);// ----> Y
    

    【讨论】:

    • 回过头来看,应该有where T : class约束,但也有可能在2012年还没有。
    【解决方案5】:

    字符串已经是引用,在 B = A 之后 B.equals(A) 将返回 true。但是,当您执行 B = "abcd" 时,您正在做相同的事情,您将 B 分配给对字符串文字的引用。

    您想要做的是修改字符串指向的数据,但是,因为 .NET 中的字符串是不可变的,所以没有办法这样做。

    【讨论】:

      【解决方案6】:

      字符串是 C# 中的特殊对象,因为它们是不可变的,否则它将是通过引用。你可以运行这个sn-p来查看。

      public class Foo
      {
        public string strA;
      }
      
      Foo A = new Foo() { strA = "abc" };
      Foo B = A;
      
       B.strA = "abcd";            
      
       Console.WriteLine(A.strA);// abcd
       Console.WriteLine(B.strA);//abcd
      

      【讨论】:

        【解决方案7】:

        你要做的就是:

        string A = "abc";
        ref string B = ref A;
        B = "abcd"; // A was assigned to B as reference, so changing B is the same as changing A
        Console.WriteLine(A); // abcd
        Console.WriteLine(B); // abcd
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-12
          • 2018-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-01
          • 1970-01-01
          • 2019-02-15
          相关资源
          最近更新 更多