【问题标题】:How to pass in the "modifier" string returned by the function?如何传入函数返回的“修饰符”字符串?
【发布时间】:2013-01-28 14:16:22
【问题描述】:
class test
{
  public String get() {return s;}
  private String s="World";
}

class modifier
{
   public static void modify(ref String v)
   {
     v+="_test";
   }
}

String s1="Earth";


modifier.modify(ref s1); <-------- OK

test c=new test();
modifier.modify(ref c.get()); <------- Error

如何传入函数返回的“修饰符”字符串? 通过另一个 String 对象进行赋值是不可接受的。那么副本将如何创建。

【问题讨论】:

  • 记住:字符串是不可变的类型。您不能更改它们。
  • public String get() {return s;} private String s="World";不确定,但尝试改变这两个的顺序,把私人放在第一位
  • "ref" 允许我将字符串作为参数传递并更改它。有没有这样的机制来获取字符串作为函数的结果?
  • 公共静态字符串修改(String v) { return v + "_test"; }
  • 只返回新字符串。请注意,当您通过 ref 传递字符串时,您将通过 ref 返回一个 NEW 字符串(旧字符串消失)。

标签: c# string ref


【解决方案1】:

您正在尝试用 C# 编写 C++ 代码。您需要以 C# 方式处理此问题。 为 test.s 添加一个属性,而不是一个名为“get()”的方法。 我们将在下面的代码中将此新属性称为“MyString”:

class test
{
    public String MyString
    {
        get
        {
            return s;
        }

        set
        {
            s = value;
        }
    }

    private String s = "World"; 
}

class modifier
{
    public static string modify(String v)
    {
        return v + "_test";
    }
}

test c = new test();
c.MyString = modifier.modify(c.MyString);

【讨论】:

    【解决方案2】:

    如果您不喜欢 Matthew Watson 的回答并且您想坚持自己的方法,那么可以使用 StringBuilder。这是一个无需创建新字符串即可更改其值的字符串!

    我的意思是:
    普通字符串的值无法更改,正在发生的事情是正在创建一个新字符串......并且指针(指向您要更改其值的字符串)从现在开始指向这个新字符串。所有其他指针......“指向”旧字符串......仍然指向......旧字符串!(字符串的值没有改变!)
    我不确定这是否足够清楚,但如果你想玩 Strings,你必须理解这一点。这正是 s1 不能改变其值的原因。

    解决方法是使用 StringBuilder:

        class test
    {
        public StringBuilder get() { return  s; }
        private StringBuilder s = new StringBuilder("World");
    }
    
    class modifier
    {
        public static void modify(StringBuilder v)
        {
            v.Append("_test");
        }
    }
    

    还有一些测试代码:(当然,所有这些都伴随着处理成本……但我认为现在这不是问题)

            StringBuilder s1 = new StringBuilder("Earth");
    
            System.Diagnostics.Debug.WriteLine("earth is {0}", s1);
            modifier.modify(s1); //<-------- OK
            System.Diagnostics.Debug.WriteLine("earth is {0}",s1);
    
            test c=new test();
            StringBuilder aa=c.get();
            System.Diagnostics.Debug.WriteLine("earth is {0}", aa);
            modifier.modify(aa); //<------- Error(not anymore)
            System.Diagnostics.Debug.WriteLine("earth is {0}", c.get());
    

    在使用代码之前,请尝试了解 String 和 StringBuilder 的工作原理

    【讨论】:

    • 谢谢。有趣的选择。
    • 希望它可以帮助您清除问题。在继续之前了解您的代码为什么不起作用非常重要。
    • 在这种情况下,modify 方法的参数可能不应该是ref。毕竟参数不是在方法体内部重新赋值的,是引用类型。
    【解决方案3】:

    你必须创建一个临时变量:

    string tmp = c.get();
    modifier.modify(ref tmp);
    

    因为您通过引用传递参数。

    【讨论】:

    • 我无法创建副本。我需要更改测试类的字符串。
    • 然后,在 test 类中添加一个 set() 方法。
    • @Mixer 你不能改变字符串。字符串是不可变的类型。
    • 函数的结果不会占用内存中的特定空间,除非它被分配给一个变量。做不到。
    • @JustAnotherUserYouMayKnow 当人们说“更改字符串”时,显然他们真正的意思是“更改字段(或变量)的 reference 以引用另一个字符串实例”。
    【解决方案4】:

    test 的设计使其字段s 不能从类外部重新分配(更改为指向新对象)。那是因为sprivate,而get() 方法只返回 s,因此不能重新分配它。

    要么更改类test 以允许外部世界以某种方式重新分配s,要么使用反射从外部访问private 字段。

    【讨论】:

      【解决方案5】:

      您可以将属性与 get/set-eccessor 一起使用,然后将 test 对象传递给 test

      class test
      {
          public String myString 
          { 
               get { return s; } 
               set { s = value; } 
          }
      
          private String s="World";
      }
      
      class modifier
      {
          public static void modify(test myTest)
          {
              myTest.myString += "_test";
          } 
      }
      

      test c = new test();
      modifier.modify(c);
      
      Console.WriteLine(c.myString); //World_test
      

      【讨论】:

        猜你喜欢
        • 2011-12-30
        • 1970-01-01
        • 2011-07-09
        • 1970-01-01
        • 2022-10-14
        • 1970-01-01
        • 2013-02-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多