c# - 标记为只读的值类型字段的意外行为
问题描述
我有一个类似的情况:
struct A
{
string[] strs;
public A(int cap) => strs = new string[cap];
public void Set(int i, string s) => strs[i] = s;
}
class B
{
readonly A a = new A(5);
public void Set(int i, string s) => a.Set(i, s);
}
并且我Set
在 class 上调用该方法B
,但是 in 中的数组a
没有改变,但是,如果我删除readonly
关键字,则该方法按预期工作并且数组被更改。
我意识到A
应该是一个类而不是一个结构,但我主要只是想了解为什么会发生这种情况。
解决方案
您所报告的内容听起来就像您实际设置的真实代码中的一个字段(A
问题中的代码的行为与声称的方式不同)。例如,此代码将以这种方式失败:
class Program
{
static void Main(string[] args)
{
var b = new B();
b.Set("abc");
// writes "init" if readonly left in, "abc" otherwise
Console.WriteLine(b.ToString());
}
}
struct A
{
string _s;
public A(int cap) => _s = "init";
public void Set(string s) => _s = s;
public override string ToString() => _s;
}
class B
{
readonly A a = new A(5);
public void Set(string s) => a.Set(s);
public override string ToString() => a.ToString();
}
这样做的原因是,使用readonly
, 调用a.Set()
实际上是:
var tmp = a;
tmp.Set(); // operates on a clone
这正是因为它想要保证readonly
字段声明的一部分 - 否则调用会Set()
产生改变只读字段值的副作用。以最简单的方式避免这种情况:避免使用可变结构!在最近的 C# 版本(7.2+)中,你可以将readonly struct
结构声明为("ref readonly") 修饰符的更有效实现)。in
推荐阅读
- activemq - ActiveMQ - 限制队列中未决消息的数量而不影响生产者
- python-2.7 - python-sockets:通过不同的网络发送数据
- r - Shiny -- 'ggsave' 打印的图看起来与闪亮的应用程序中显示的图不同
- android - 动态下载字体文件并用于Android和IOS
- python - 两个列表中所有元素的乘法
- html - 从角度 6 中的另一个组件传递值后,如何动态检查复选框?
- javascript - Vue路由器自动在路径上添加哈希
- webhooks - Dialogflow Webhook 格式与对话 Webhook 格式
- python - 为什么 itertools.product(*empty_list) 在列表中返回一个空元组?
- angular - Apache如何反向代理aspnet核心api和anular 6应用程序