if (someState != otherState & someState == otherOtherState | [...])
{
// follow some logic path
}
else
{
// follow some other path
}
// Or
if (someState != otherState && someState == otherOtherState || [...])
{
// follow some logic path
}
else
{
// follow some other path
}
What is the difference between these two statements?
if (someState != someOtherState && someState == someOtherOtherState || someState == someOtherOtherOtherState || someState == someOtherOtherOtherOtherState)
{
[...]
}
else
{
[...]
}
The common resolution to this is to create a method which returns a Boolean value based upon the return of a number of logical expressions (again limited because of code analyzers); e.g.:
if (SomeStateMethod())
{
[...]
}
else
{
[...]
}
[...]
private boolean SomeStateMethod()
{
return someState != someOtherState && someState == someOtherOtherState || someState == someOtherOtherOtherState || someState == someOtherOtherOtherOtherState;
}
All you are doing here is moving a group of expressions to be evaluated by a method rather than using the expressions in your if/if...else/if...elseif statement. The code analyzer will still ding your method if it breaches the logical expression contract, which then would cause you to create another method for more logical expressions, so forth and so on. Granted many of this can be resolved by creating less complex objects and comparison methods, etc.; but I digress.
var expressions = new[]
{
true,
true,
true,
false,
true
};
return expressions.All(x => x);
For VB.NET developers, the above would look like this:
Dim expressions = New()
{
True,
True,
True,
False,
True
}
Return expressions.All(Function(x) x)
The problem with this is that Any or All will not short-circuit the execution. Any is the counter operative of the binary logical operator | [Or for VB.NET developers]; while All is the counter operative of the binary logical operator & [And for VB.NET developers].
var expressions = new Func<bool>[]
{
() => { return true; },
() => { return true; },
() => { return true; },
() => { return false; },
() => { return true; }
};
return expressions.All(x => x.Invoke());
VB.NET example:
Dim expressions = New Func(Of Boolean)() _
{
Function() True,
Function() True,
Function() True,
Function() False,
Function() True
}
Return expressions.All(Function(x) >= x.Invoke())
Granted it will take a few nanoseconds more than your standard logical expressions, but it will provide a short-circuit option where you have methods/logical expressions which run deep into an objects method/property path while retaining a cleaner and more concise logical expression series.
using System;
using System.Linq;
using System.Runtime.CompilerServices;
namespace EE_A35779
{
class Program
{
static void Main(string[] args)
{
NonShortCurcuitedNonLinq();
Console.WriteLine();
ShortCurcuitedNonLinq();
Console.WriteLine();
NonShortCircuitedLinq();
Console.WriteLine();
ShortCircuitedLinq();
Console.ReadLine();
}
static bool NonShortCurcuitedNonLinq()
{
return LogAndReturn(false) & LogAndReturn(true) & LogAndReturn(true) & LogAndReturn(true) & LogAndReturn(true);
}
static bool ShortCurcuitedNonLinq()
{
return LogAndReturn(false) && LogAndReturn(true) && LogAndReturn(true) && LogAndReturn(true) && LogAndReturn(true);
}
static bool NonShortCircuitedLinq()
{
var expressions = new[]
{
LogAndReturn(false),
LogAndReturn(true),
LogAndReturn(true),
LogAndReturn(true),
LogAndReturn(true)
};
return expressions.All(x => x);
}
static bool ShortCircuitedLinq()
{
var expressions = new Func<bool>[]
{
() => { return LogAndReturn(false); },
() => { return LogAndReturn(true); },
() => { return LogAndReturn(true); },
() => { return LogAndReturn(true); },
() => { return LogAndReturn(true); }
};
return expressions.All(x => x.Invoke());
}
static bool LogAndReturn(bool value, [CallerMemberName] string method = "")
{
Console.WriteLine($"{method} - {value}");
return value;
}
}
}
Imports System.Runtime.CompilerServices
Module Program
Sub Main(args As String())
NonShortCurcuitedNonLinq()
Console.WriteLine()
ShortCurcuitedNonLinq()
Console.WriteLine()
NonShortCircuitedLinq()
Console.WriteLine()
ShortCircuitedLinq()
Console.ReadLine()
End Sub
Function NonShortCurcuitedNonLinq() As Boolean
Return LogAndReturn(False) And LogAndReturn(True) And LogAndReturn(True) And LogAndReturn(True) And LogAndReturn(True)
End Function
Function ShortCurcuitedNonLinq() As Boolean
Return LogAndReturn(False) AndAlso LogAndReturn(True) AndAlso LogAndReturn(True) AndAlso LogAndReturn(True) AndAlso LogAndReturn(True)
End Function
Function NonShortCircuitedLinq() As Boolean
Dim expressions =
{
LogAndReturn(False),
LogAndReturn(True),
LogAndReturn(True),
LogAndReturn(True),
LogAndReturn(True)
}
Return expressions.All(Function(x) x)
End Function
Function ShortCircuitedLinq() As Boolean
Dim expressions = New Func(Of Boolean)() _
{
Function() LogAndReturn(False),
Function() LogAndReturn(True),
Function() LogAndReturn(True),
Function() LogAndReturn(True),
Function() LogAndReturn(True)
}
Return expressions.All(Function(x) x.Invoke())
End Function
Function LogAndReturn(ByVal value As Boolean, <CallerMemberName> ByVal Optional method As String = "")
Console.WriteLine($"{method} - {value}")
Return value
End Function
End Module
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (0)