停止Regex.Replace修改原始变量

时间:2020-01-26 15:50:50

标签: c# string

InsertWords()函数无意中修改了文本变量。如果变量text.text为“ exampleˣhere”,而变量text.words [0]为“ TEST”,则InsertWords()函数会将text.text更改为“ example TEST here”。我希望text变量保持不变,而只有textCopy变量更改。我该怎么办?为什么即使我从未使用过regex.Replace,text.text仍会更改?

public class TextClass {

    public List<string> words;
    public string text;
    public string name;
    public string date;
    public string id;

}

public TextClass text;

public TextClass InsertWords()
    {
        Regex regex = new Regex(Regex.Escape("ˣ"));

        TextClass textCopy = text;

        foreach (string word in inputWords)
        {
            textCopy.text = regex.Replace(textCopy.text, word, 1);
        }

        return textCopy;
    }

编辑:我使用这样的功能

public Display display;

display.DisplayText(InsertWords());

public class Display {

    public Text text;

    public void DisplayText (TextClass text_)
    {
        text.text = text_.text;
    }

}

2 个答案:

答案 0 :(得分:3)

要拥有一个类的副本,您需要创建该类的新实例。您可以使用这样的构造函数来实现。我也将您所有的字段都更改为属性。

public class TextClass
{
    // You don't need to set the list externally, just get it to add/remove/iterate
    public List<string> Words { get; } = new List<string>();
    public string Text { get; set; }
    public string Name { get; set; }
    public string Date { get; set; }
    public string Id { get; set; }

    public TestClass() { } // default constructor

    public TestClass(TestClass from) // copy constructor
    {
        Text = from.Text;
        Name = from.Name;
        Date = from.Date;
        Id = from.Id;
        Words.AddRange(from.Words); // this ensures a deep copy of the list
    }    
}

那你就可以做

TextClass textCopy = new TextClass(text);

并且textCopy将是text的真实深层副本,并且当您将某些内容分配给textCopy.Text时,它将不会影响text.Text

或者,您可以制作这样的复制方法

public class TextClass
{
    // You don't need to set the list externally, just get it to add/remove/iterate
    public List<string> Words { get; } = new List<string>();
    public string Text { get; set; }
    public string Name { get; set; }
    public string Date { get; set; }
    public string Id { get; set; }

    public TestClass Copy()
    {
        var copy = new TestClass()
        {
            Text = this.Text;
            Name = this.Name;
            Date = this.Date;
            Id = this.Id;
        }
        copy.Words.AddRange(this.Words); // this ensures a deep copy of the list
        return copy;
    }    
}

并像这样使用它

TextClass textCopy = text.Copy();

答案 1 :(得分:1)

另一种更“流畅”的方法是创建返回新实例的方法,这些实例明确说明正在发生的变化。这样一来,您就可以使整个对象变得不可变,并最大程度地重用不变的嵌套对象,其他人也更容易理解。

例如,无需克隆Words属性:

public class TextClass
{
    // No mutable properties (ideally replace List with IReadonlyCollection too)
    public List<string> Words { get; }
    public string Text { get; }
    public string Name { get; }
    public string Date { get; }
    public string Id { get; }

    public TestClass (List<string> words, string text, string name, string date, string id)
    {
       this.Words = words ?? throw new ArgumentNullException(nameof(words));
       ...
    }

    public TestClass WithNewText(string text) =>
       new TestClass(this.Words, text, this.Name, this.Date, this.Id);
 }