使用||运营商,Microsoft在此描述了短路评估Short Circuit Evaluation
但是,我有以下代码似乎与此过程相矛盾:
if ((_opcLoaded || DoLoadOPC()) &&
(_tagsAdded || DoAddTags()) &&
DoWriteRecipe() &&
(DoResume()))
我试图阻止的是如果_tagsAdded为真,则调用DoAddTags函数(DoAddTags将_tagsAdded设置为true)。
然而,即使DoAddTag
为真,我也发现_tagsAdded
被调用了。 _opcLoaded
和DoLoadOPC
的情况相同。我必须在DoAddTags
内添加一个条件来检查_tagsAdded
,这不应该是必要的。
有人可以解释为什么会这样吗?
这是完整代码
//
// Resume a Paused recipe
case MonitoredTasks.Resume:
Task.Factory.StartNew(() =>
{
MonitoredTask = MonitoredTasks.None;
if ((_opcLoaded || DoLoadOPC()) &&
**(_tagsAdded || DoAddTags())** &&
DoWriteRecipe() &&
(DoResume()))
{
MonitoredTask = MonitoredTasks.None;
RunningState = RecipeRunningStates.Running;
Status = CIPStatuses.Running;
}
else
{
MonitoredTask = MonitoredTasks.Resume;
}
});
break;
DoAddTags的代码
/// <summary>
/// Adds all necessary tags to the OPC Server Manager
/// </summary>
/// <returns></returns>
bool DoAddTags()
{
bool result = false;
var oldActivity = Activity;
//
// Not doing anything OPC related?
if (Activity != CIPActivities.AddingOPCTags && !_tagsAdded && Activity != CIPActivities.StartingOPC)
{
lock (_locks[LOCK_OPC])
{
Activity = CIPActivities.AddingOPCTags;
Status = CIPStatuses.Initialising;
RecipeError = Errors.None;
try
{
//
// Reset connection and internal tags list
_serverManager.Reset();
//
// Now to add all OPC Tags - Area
CIPStatusTag = _serverManager.AddTag(_area.CIPStatusTag);
RecipeIDTag = _serverManager.AddTag(_area.RecipeIDTag);
RecipeInstructionIDTag = _serverManager.AddTag(_area.RecipeInstructionIDTag);
HandshakingTag = _serverManager.AddTag(_area.HandshakingTag);
GlobalInstructionIDTag = _serverManager.AddTag(_area.GlobalInstructionIDTag);
InstructionAttemptsTag = _serverManager.AddTag(_area.InstructionAttemptsTag);
//
// Area tags OK?
if (CIPStatusTag == null || RecipeIDTag == null || RecipeInstructionIDTag == null || HandshakingTag == null || GlobalInstructionIDTag == null || InstructionAttemptsTag == null)
{
RecipeError = Errors.InvalidAreaTags;
DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags - Invalid AREA Tags"), Sender = this });
}
else
{
VM_CIPInstruction vm = null;
bool instructionTagErrors = false;
//
// For each area instruction that is used, assig a link to the instruction
foreach (var i in _areaInstructions)
{
//
// Create a View Model for the specified area instruction : this allows us to determine the number of parameters (tags) that apply to the instruction
vm = new VM_CIPInstruction(i.Value.Instruction);
//
// Assign device reference tags
if (vm.DeviceReferencesAvailable)
{
i.Value.DeviceTag = _serverManager.AddTag(i.Value.Instruction.DeviceReferenceTag);
instructionTagErrors = i.Value.DeviceTag == null;
}
//
// For each required parameter, add tag
for (int paramNo = 1; paramNo <= vm.NoOfParams; paramNo++)
{
switch (paramNo)
{
case 1:
//
// Tag defined? Add it
if (vm.AreaInstruction.Param1Tag >= 0)
{
i.Value.Param1 = _serverManager.AddTag(i.Value.Instruction.Param1Tag);
if (i.Value.Param1 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 2:
//
// Tag defined? Add it
if (vm.AreaInstruction.Param2Tag >= 0)
{
i.Value.Param2 = _serverManager.AddTag(i.Value.Instruction.Param2Tag);
if (i.Value.Param2 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 3:
//
// Tag defined? Add it
if (vm.AreaInstruction.Param3Tag >= 0)
{
i.Value.Param3 = _serverManager.AddTag(i.Value.Instruction.Param3Tag);
if (i.Value.Param3 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 4:
//
// Tag defined? Add it and then check quality
if (vm.AreaInstruction.Param4Tag >= 0)
{
i.Value.Param4 = _serverManager.AddTag(i.Value.Instruction.Param4Tag);
if (i.Value.Param4 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 5:
//
// Tag defined? Add it and then check quality
if (vm.AreaInstruction.Param5Tag >= 0)
{
i.Value.Param5 = _serverManager.AddTag(i.Value.Instruction.Param5Tag);
if (i.Value.Param5 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
case 6:
//
// Tag defined? Add it and then check quality
if (vm.AreaInstruction.Param6Tag >= 0)
{
i.Value.Param6 = _serverManager.AddTag(i.Value.Instruction.Param6Tag);
if (i.Value.Param6 == null)
{
instructionTagErrors = true;
}
}
else
{
instructionTagErrors = true;
}
break;
}
}
if (instructionTagErrors)
{
RecipeError = Errors.InvalidInstructionTags;
DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage(String.Format("CIPRecipe.DoAddTags - Invalid Instruction {0} Tags", vm.Name)), Sender = this });
break;
}
}
//
// Any problems adding tags?
if (RecipeError == Errors.None)
{
Activity = CIPActivities.StartingOPC;
//
// Once all tags added, start OPC Server
result = _serverManager.Start();
if (!result)
{
Status = CIPStatuses.AddTagsFailed;
RecipeError = Errors.OPC;
DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags - Start of OPC failed"), Sender = this });
}
else
{
**_tagsAdded = true;**
Status = CIPStatuses.TagsAdded;
}
}
else
{
Status = CIPStatuses.AddTagsFailed;
}
}
}
catch (Exception ex)
{
RecipeError = Errors.Exception_AddTags;
DoError(new RecipeErrorHandlerEventArgs(this) { Message = FormatMessage("CIPRecipe.DoAddTags"), Exception = ex, Sender = this });
}
finally
{
Activity = oldActivity;
}
}
}
return Status == CIPStatuses.TagsAdded;
}
我用**
突出显示了相关的行在第一次执行时,执行DoAddTags并将_tagsAdded设置为TRUE-我在这里放置了一个断点,所以我知道它正在被设置。不久之后(有或没有前断点)再次输入DoAddTags(在第一行),尽管_doAddTags == true。
我甚至在代码上设置了断点&#34; (_ tagsAdded || DoAddTags())&#34;。 _tagsAdded == true,但仍然输入了DoAddTags。
所以我所看到的是,并且所有的手表/调试信息都与之一致是在调用DoAddTags而_tagsAdded == true
答案 0 :(得分:2)
此代码不会显示您描述的行为,短路的工作原理如上所述。
实际发生的事情:_tagsAdded
最初为false
,因此调用了DoAddTags()
,将_tagsAdded
设置为true
。
然后调试器启动,您检查_tagsAdded
并看到它是true
。
而是使用F11逐步执行代码并检查或观察所有相关变量。