C# readonly field's property still allowed mod

2020-04-14 16:11发布

I would like to ask, if I pass a object to a constructor of a class,the object will be a readonly field of the class,and I modify the property of the object,the property inside the class will also change,I guess it's call by reference.Is there any way to do this better/prevent? thanks

private void Form1_Load(object sender, EventArgs e)
{
    Product p = new Product() { Name="New" };
    Store s = new Store(p);
    p.Name = "MODIFY!";
    MessageBox.Show(s.Show());//MODIFY!
}

public class Store
{
    private readonly Product product;

    public Store(Product product)
    {
        this.product = product;
    }

    public string Show()
    {
        return this.product.Name;
    }
}

public class Product
{
    public string Name { get; set; }
}

标签: c#
3条回答
2楼-- · 2020-04-14 16:28

If you don't want product inside of Store to change if you change the original instance, you have to make a copy before assigning it to the field:

public Store(Product product)
{
    this.product = new Product() {Name = product.Name};
}

Alterantively, you could make Product a struct. Structs are always copied when passed to a method, and not passed by reference:

public struct Product
{
    public string Name { get; set; }
}
查看更多
甜甜的少女心
3楼-- · 2020-04-14 16:35

What you store in your readonly field is a reference. And that reference of course is readonly and never changed. But the content of the referenced object can still be changed.

Since Product seems to be a data-holding class, one approach might be to simply copy the content into a new instance:

public class Store
{
    private readonly Product product;

    public Store(Product product)
    {
        // Create a new Product instance that only this Store instance
        // knows about
        this.product = new Product { Name = product.Name };
    }
}

Now the content of Store.product cannot be changed from outside as long as you don't export this instance.
But note that code inside the Store class may still be able to change the content.

查看更多
家丑人穷心不美
4楼-- · 2020-04-14 16:44

Another option is creating an immutable version of Product:

public class Product
{
    public string Name { get; set; }

    public Immutable ToImmutable() => new Immutable(this);

    public class Immutable
    {
         public Immutable(Product product) { Name = product.Name; }
         public string Name { get; }
    }
}

And now,

public class Store
{
    private readonly Product.Immutable product;

    public Store(Product product)
    {
        this.product = product.ToImmutable();
    }

    public string Show()
    {
        return this.product.Name;
    }
}

Benefits? No one can mess around with product inside Store.

查看更多
登录 后发表回答