属性似乎在方法调用之间改变,但没有代码应该改变它
本文关键字:改变 代码 方法 调用 属性 之间 | 更新日期: 2023-09-27 18:07:36
我有一个Octet
类,应该"包装"8个样品,然后将它们发送出去。它有方法添加一个新的样本,检查它是否已经满了,并从Octet
的八个值中提取一个Frame
数据结构。
Octet
类抛出两种异常:"未满不能提取"answers"已满不能添加样本"。为此,客户端代码应该在调用Add
之前检查是否已满,并在已满时立即提取,以及重置它(老实说,这是一个相当蹩脚的类契约)。
问题是:我得到两种错误,即使客户端类-唯一使用Octet
的-似乎在抛出操作之前正确执行检查,但即使错误条件正在被击中。更糟糕的是,当我在调试器中断时检查值时,它们是正确的,也就是说,异常不应该被抛出!
public class Client
{
private Octet _octet = new Octet();
void ProcessNewSamples(IEnumerable<int> newSamples)
{
foreach (int sample in newSamples)
{
if (!_octet.IsFull)
{
_octet.Add(sample);
}
if (_octet.IsFull)
{
var frame = _octet.ExtractFrame();
this.SendElsewhere(frame);
_octet.Reset();
}
}
}
}
public class Octet
{
const int ARRAY_SIZE = 8;
int[] _samples = new int[ARRAY_SIZE];
int _index = 0;
public bool IsFull { get { return _index >= 8; } }
public void Add(int sample)
{
if (IsFull)
{
throw new InvalidOperationException();
}
else
_samples[_index++] = sample;
}
public Frame<int> ExtractFrame()
{
if (!IsFull)
throw new InvalidOperationException();
else
return new Frame<int>(_samples);
}
public void Reset()
{
_samples = new int[ARRAY_SIZE];
_index = 0;
}
}
正如在注释中提到的,如果函数是并行访问的,那么应该设置一个锁。
如果SendElsewhere
很快,我就把锁放在函数周围:
void ProcessNewSamples(IEnumerable<int> newSamples)
{
lock (this)
{
foreach (int sample in newSamples)
{
if (!_octet.IsFull)
{
_octet.Add(sample);
}
if (_octet.IsFull)
{
var frame = _octet.ExtractFrame();
this.SendElsewhere(frame);
_octet.Reset();
}
}
}
}
否则我将收集所有帧并在之后发送它们:
void ProcessNewSamples(IEnumerable<int> newSamples)
{
var frames = new List<Frame>();
lock (this)
{
foreach (int sample in newSamples)
{
if (!_octet.IsFull)
{
_octet.Add(sample);
}
if (_octet.IsFull)
{
var frame = _octet.ExtractFrame();
frames.Add(frame);
_octet.Reset();
}
}
}
foreach (var frame in frames)
{
this.SendElsewhere(frame)
}
}