简体   繁体   English

C#-在引用类型上使用私有setter和公共getter

[英]C# - Using a private setter with a public getter on reference types

Consider the following short code example with a public getter and a private setter: 考虑以下带有公共获取器和私有设置器的简短代码示例:

public class Foo        
{
    public class Bar
    {
        ...
    }

    public Bar fooBar { get; private set; }
    public int valueType { get; private set; }
}

I want to make sure that the class members can only be written to from inside the Foo class. 我想确保只能从Foo类内部将类成员写入。 That works for value types like valueType in the example above. 这适用于上面示例中的值类型(如valueType But how do reference types like the nested class fooBar behave? 但是像嵌套类fooBar这样的引用类型如何表现呢?

Can I use the reference which is returned by the public getter, to manipulate my private member? 我可以使用公共获取者返回的引用来操纵我的私有成员吗?

If the type you're referring to is mutable, then yes, anyone with a reference to the "container" can fetch a reference and then mutate the object. 如果您要引用的类型是可变的,那么可以,任何引用了“容器”的人都可以获取引用,然后对对象进行突变。 For example: 例如:

using System;
using System.Collections.Generic;

class Container
{
    public List<string> List { get; private set; }
        = new List<string>();
}

class Program
{
    static void Main()
    {
        var container = new Container();
        var list = container.List;
        Console.WriteLine(list.Count); //0

        container.List.Add("foo");
        Console.WriteLine(list.Count); // 1        
    }
}

Here the List<string> is being mutated outside Container . 在这里, List<string>Container之外被突变。 One option to avoid this would be to use a read-only view over the mutable data: 一种避免这种情况的选择是对可变数据使用只读视图:

using System;
using System.Collections.Generic;

class Container
{
    private readonly List<string> list = new List<string>();

    public IReadOnlyList<string> ListView { get; }

    public Container()
    {
        ListView = list.AsReadOnly();
    }

    public void AddItem(string item)
    {
        list.Add(item);
    }
}

class Program
{
    static void Main()
    {
        var container = new Container();
        Console.WriteLine(container.ListView.Count); //0

        // container.ListView.Add("foo"); // Compile-time error

        container.AddItem("foo");
        Console.WriteLine(container.ListView.Count); // 1        
    }
}

Note that you shouldn't just return the list directly from the property, even if the compile-time type is IReadOnlyList<T> - because then a caller could just cast back to List<T> and mutate it. 请注意,即使编译时类型为IReadOnlyList<T> ,您也不应该直接从属性中直接返回列表,因为那样的话,调用者可以直接将其转换回List<T>并对其进行突变。 List<T>.AsReadOnly() returns a genuinely read-only wrapper object around the list, so callers really won't be able to mutate it. List<T>.AsReadOnly()在列表周围返回一个真正的只读包装对象,因此调用者实际上无法对其进行突变。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM