C# - 在引用类型上使用私有 setter 和 public getter
C# - Using a private setter with a public getter on reference types
考虑以下带有 public getter 和私有 setter 的简短代码示例:
public class Foo
{
public class Bar
{
...
}
public Bar fooBar { get; private set; }
public int valueType { get; private set; }
}
我想确保 class 成员只能从 Foo
class 内部写入。这适用于上面示例中的 valueType
等值类型。但是像嵌套的 class fooBar
这样的引用类型是如何表现的呢?
我可以使用 public getter 返回的引用来操纵我的私有成员吗?
如果您引用的类型是可变的,那么是的,任何引用 "container" 的人都可以获取引用然后改变对象。例如:
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
}
}
此处 List<string>
正在 Container
外变异。避免这种情况的一种选择是对可变数据使用只读视图:
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
}
}
请注意,即使编译时类型是 IReadOnlyList<T>
,您也不应该直接 return 直接来自 属性 的列表 - 因为这样调用者就可以回退到 List<T>
并改变它。 List<T>.AsReadOnly()
return 是列表周围真正只读的包装器对象,因此调用者真的无法改变它。
考虑以下带有 public getter 和私有 setter 的简短代码示例:
public class Foo
{
public class Bar
{
...
}
public Bar fooBar { get; private set; }
public int valueType { get; private set; }
}
我想确保 class 成员只能从 Foo
class 内部写入。这适用于上面示例中的 valueType
等值类型。但是像嵌套的 class fooBar
这样的引用类型是如何表现的呢?
我可以使用 public getter 返回的引用来操纵我的私有成员吗?
如果您引用的类型是可变的,那么是的,任何引用 "container" 的人都可以获取引用然后改变对象。例如:
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
}
}
此处 List<string>
正在 Container
外变异。避免这种情况的一种选择是对可变数据使用只读视图:
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
}
}
请注意,即使编译时类型是 IReadOnlyList<T>
,您也不应该直接 return 直接来自 属性 的列表 - 因为这样调用者就可以回退到 List<T>
并改变它。 List<T>.AsReadOnly()
return 是列表周围真正只读的包装器对象,因此调用者真的无法改变它。