属性 似乎在方法调用之间发生变化,但没有代码应该改变它
Property seems to be changing between method calls, but no code is supposed to be changing it
我有一个 Octet
class 假设 "package" 八个样本,然后将它们发送出去。它具有添加新样本、检查样本是否已满以及从 Octet
.
的八个值中提取 Frame
数据结构的方法。
Octet
class抛出两种异常:"cannot extract because not yet full"和"cannot add sample because already full"。为此,客户端代码应在调用 Add
之前检查是否已满,并在满时立即提取并重置它(老实说,这是一个非常蹩脚的 class 合同)。
问题是:我遇到了两种错误,尽管客户端 class - 唯一使用 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)
}
}
我有一个 Octet
class 假设 "package" 八个样本,然后将它们发送出去。它具有添加新样本、检查样本是否已满以及从 Octet
.
Frame
数据结构的方法。
Octet
class抛出两种异常:"cannot extract because not yet full"和"cannot add sample because already full"。为此,客户端代码应在调用 Add
之前检查是否已满,并在满时立即提取并重置它(老实说,这是一个非常蹩脚的 class 合同)。
问题是:我遇到了两种错误,尽管客户端 class - 唯一使用 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)
}
}