I'm trying to keep to the DRY principle in C#, and I was wondering if it's possible to access the argument checks in an if block. For example, would the below be possible?
if (foo == true || bar == false)
{
if (check0)
{
//foo is true
}
if (!check1)
{
//bar is false
}
}
I was also wondering if it's possible to do this, to keep the scope clean?:
if (var foo = runTimeAccessedVariable == "bar")
{
//we now have the runtime generated variable.
}
//but it doesn't exist here
Nope, it's not possible. In fact, since you use the short-circuiting || operator, the second check might not even be evaluated.
Obviously, you can work around it as follows:
var fooIsTrue = (foo == true);
var barIsFalse = (bar == false);
if (fooIsTrue || barIsFalse)
{
...
}
Note that this changes the behaviour of your code, since barIsFalse is always evaluated.
The scope and reuse can both be trivially solved by using a pair of brackets to define a new scope;
pulic void MyFunc()
{
// do stuff here in the scope of MyFunc
{
// create child scope with new scoping rules and declare control variables
var fooTrue = foo == true;
var barFalse = bar== false;
if (fooTrue || barFalse)
{
if (fooTrue)
{
//foo is true
}
if (barFalse)
{
//bar is false
}
}
}
// stuff here cannot access fooTrue, barFalse.
}
This stops the variables from 'leaking out' of this part of the function. There is a small semantic difference because the var barFalse line isn't shortcut, but it seems from your example that you'll probably need to test it anyway so it shouldn't be a concern.
Answering you second question, no it is not possible to declare a variable in this way. The only similar alternative is to use { } to create your own local scope and declare the local variable before the if statement:
{
bool foo;
if (foo = runTimeAccessedVariable == "bar")
{
}
}
In any case I'm not really sure what the benefits of this approach are. If you are insde the if statement, you already know foo is true, what is the use of having the scoped local?
Concerning your first question, I'd just push back on the whole approach. You are basically using an if statement based on a boolean expression made up of two or more conditions. Then, once inside the if statement you are discerning between what boolean condition is met or not. Also, you could have the case of an uninitialized variable, because check1 is not guaranteed to run.
I'd rewrite that completely and by-pass the need of any locally scoped variables:
Work is independent for each condition:
if (foo)
{
//whatever
}
else if (bar)
{
//whatever
}
There is common work for both conditions:
if (foo)
{
//whatever
if (bar)
{
//whatever
}
}
Both would be semantically equivalent to what you are proposing.
You can actually. You can use (extension) methods like this:
// For first case.
public static void If(this Lazy<bool>[] checks, Predicate<Lazy<bool>[]> ifCondition, Action<Lazy<bool>[]> ifAction) {
if (ifCondition(checks)) ifAction(checks);
}
// For second case.
public static void If(this object[] variables, Predicate<object[]> ifCondition, Action<object[]> ifAction) {
if (ifCondition(variables)) ifAction(variables);
}
And use of it would look like this:
// First case.
new[] { new Lazy<bool>(() => foo == true), new Lazy<bool>(() => bar == false) }.
If(checks => checks[0].Value || checks[1].Value, checks => {
if (checks[0].Value) {
//foo is true
}
if (!checks[1].Value) {
//bar is false
}
});
// Second case.
new[] { "bar" }.If(variables => (string)variables[0] == "bar", variables => {
//we now have the runtime generated variable.
});
This will limit the scope of those temporary values. However, this does not provide any check for whether you actually using checks or variables in the right way. And it would be harder to debug if something goes wrong then simple if statement.
This could also be extended to accept Func instead of Action that your If method could return result as well. And it is possible to even add ElseIf and Else methods to chain with If method (to mimic all if statement behavior).
Related
Right now I am working on a simple program, and this is a problem I've been thinking over many times. Many times I run my methods twice because of checking on the return value before running them, and I would like to know if there is a way I can prevent this, like using the returned value from the method I am checking against. It's quite hard to explain so here is a real life example from my program.
public class SFDBRepository
{
public static Domain.SF.SFObject GetSFOrder(string WorkOrd)
{
//As you can see here i'm checking on the output of this method, before trying to return it.
if (Domain.SF.SF.GetOrder(WorkOrd) != null)
{
//If the value is not null (My method returns null if no result), return the object
return Domain.SF.SF.GetOrder(WorkOrd);
}
//Same thing happens here. My method runs twice every time almost.
else if(Domain.Building_DeliveryPerformance.Building_DeliveryPerformance.GetObject(WorkOrd) != null)
{
return Domain.Building_DeliveryPerformance.Building_DeliveryPerformance.GetObject(WorkOrd);
}
else
{
return null;
}
}
}
You can simplify this down to the following code, which will only call those methods once and make the code much more readable:
public class ShopFloorDBRepository
{
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string workOrd)
{
return Domain.ShopFloor.Shopfloor.GetOrder(workOrd) ??
Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(workOrd);
}
}
To explain why this works - the ?? operator (the null-coalescing operator!) basically says "if the returned value on the left hand side of the ?? is null, then return the value of the expression on the right hand side".
This way you only need to call your functions once.
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
//As you can see here i'm checking on the output of this method, before trying to return it.
Domain.ShopFloor.ShopFloorObject wo = Domain.ShopFloor.Shopfloor.GetOrder(WorkOrd);
if (wo != null)
{
//If the value is not null (My method returns null if no result), return the object
return wo;
}
//Same thing happens here. My method runs twice every time almost.
Domain.ShopFloor.ShopFloorObject yowo = Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(WorkOrd);
if(yowo != null)
{
return yowo;
}
/* default return */
return null;
}
PS
You're kinda doing the "Factory Pattern"
See
http://www.dofactory.com/net/factory-method-design-pattern
Looks to me like you could be using a temporary variable to hold the result, which you can test and return.
public class ShopFloorDBRepository
{
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
var result = Domain.ShopFloor.GetOrder(WorkOrd);
if (result != null) return result;
...
This is a common paradigm, especially when the method being called is expensive and/or has side effects you don't wish to incur twice.
Here, the "var" declaration sets the type of "result" to the type returned by the method being called; you could also use the name of the actual type.
If you wish to make two different kinds of tests like this, you'll need two different variables unless they have the same type (which in this case it appears they do).
An alternate mechanism that does require the full type, that you'll also see:
public static ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
ShopFloorObject result;
if ( (result = Domain.ShopFloor.GetOrder(WorkOrd)) != null )
return result;
if ( (result = Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(WorkOrd)) != null)
return result;
return null;
Here you're explicitly declaring the type of the return value, then making the two calls you've indicated, testing the results against null, and returning the first non-null value.
I'm writing a Rosyln analyser/analyzer. It checks to ensure that a method is called before accessing another (potentially dangerous) method on a type. To show what I mean, here's some bad code that I want to analyse and fail on:
private void myMethod()
{
var myThing = new MyThing();
myThing.Value = null;
string value = myThing.GetValue(); // code blows up here as the internal value is null
}
Here's code that's OK because it calls a method that says whether it's null:
private void myMethod()
{
var myThing = new MyThing();
myThing.Value = null;
if(!myThing.HasValue)
{
return ;
}
string value = myThing.GetValue();
}
So, it should check that all calls to GetValue are preceeded by a call to HasValue.
I've just started with Roslyn, so there's probably a more elegant way than my initial (failing) attempt at:
1 - Declare that I want to inspect invocation expressions
context.RegisterSyntaxNodeAction(analyseMemberAccessNode, SyntaxKind.InvocationExpression);
2 - In my method, I get the method name (GetValue())
var expr = (InvocationExpressionSyntax)context.Node;
var memberAccess = expr.Expression as MemberAccessExpressionSyntax;
if (memberAccess?.Name.ToString() != "GetValue")
return;
3 - I then check to see if it's the right 'GetValue'
var memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccess).Symbol as IMethodSymbol;
if (!memberSymbol?.OverriddenMethod.ToString().StartsWith("MyNamespace.MyThing.GetValue") ?? true)
return;
4 - Up to here, everything is fine. So I get the name of the variable
var e = memberAccess.Expression as IdentifierNameSyntax;
string variableName = e.Identifier.Text;
5 - now I'm stuck - my theory was to; get the containing method, find the single variable declaration that matches variableName, find usages of that, and ensure that HasValue is called before GetValue.
In short, using a Roslyn analyser (deriving from DiagnosticAnalyzer), how do I ensure that HasValue is called before GetValue?
Instead of registering for each Invocation, you might be better off registering for the entire method declaration. Then you can keep track of all MemberAccessExpressionSyntax and ensure that for a given variable that HasValue is called before GetValue. To do that, I would get the MemberAccessExpressionSyntax descendants from the MethodDeclaration node.
context.RegisterSyntaxNodeAction((analysisContext) =>
{
var invocations =
analysisContext.Node.DescendantNodes().OfType<MemberAccessExpressionSyntax>();
var hasValueCalls = new HashSet<string>();
foreach (var invocation in invocations)
{
var e = invocation.Expression as IdentifierNameSyntax;
if (e == null)
continue;
string variableName = e.Identifier.Text;
if (invocation.Name.ToString() == "HasValue")
{
hasValueCalls.Add(variableName);
}
if (invocation.Name.ToString() == "GetValue")
{
if (!hasValueCalls.Contains(variableName))
{
analysisContext.ReportDiagnostic(Diagnostic.Create(Rule, e.GetLocation()));
}
}
}
}, SyntaxKind.MethodDeclaration);
Here's code I write to check if properties in my viewmodel are null or not before attempting to update the database
var channel = _context.Channels.FirstOrDefault(x => x.Id == viewModel.Id);
if (!string.IsNullOrEmpty(viewModel.Part))
{
channel.Part = viewModel.Part;
}
if (!string.IsNullOrEmpty(viewModel.IndexName))
{
channel.IndexName = viewModel.IndexName;
}
if (viewModel.MeasurementId != null)
{
channel.MeasurementId = viewModel.MeasurementId;
}
if (!string.IsNullOrEmpty(viewModel.Direction))
{
channel.Direction = viewModel.Direction;
}
The code is working fine but I use alot of if statements here which for me doesn't look really effective. Can you suggest me changes like using other syntax or structures rather than if statement to make my code more concise and abit more "pro"?
As long as your channel object's properties do not have any side-effects other than changing a value (ie, firing events), you could do this:
string PickNonEmptyOrDefault(string value, string deflt)
{
return String.IsNullOrEmpty(value) ? deflt : value;
}
...
channel.Part = PickNonEmptyOrDefault(viewModel.Part, channel.Part);
channel.IndexName = PickNonEmptyOrDefault(viewModel.IndexName, channel.IndexName);
etc.
By the way, I wanted to know if there was a way this could be done without accidentally side effecting your property. The trick is to use reflection and to use a PropertyInfo object to do your work:
class Foo
{
public string Bar { get; set; }
public string Baz { get; set; }
public override string ToString()
{
return (Bar ?? "") + " " + (Baz ?? "");
}
}
delegate void propsetter(string prop, string value);
private static void SetOnNonEmpty(PropertyInfo pi, Object o, string value)
{
if (pi.PropertyType != typeof(string))
throw new ArgumentException("type mismatch on property");
if (!String.IsNullOrEmpty(value))
pi.SetValue(o, value);
}
static void Main(string[] args)
{
var myObj = new Foo();
myObj.Baz = "nothing";
PropertyInfo piBar = myObj.GetType().GetProperty("Bar");
PropertyInfo piBaz = myObj.GetType().GetProperty("Baz");
SetOnNonEmpty(piBar, myObj, "something");
SetOnNonEmpty(piBaz, myObj, null);
Console.WriteLine(myObj);
}
output something nothing
I honestly don't recommend doing this as it doesn't really add to the readability and feels pretty gross.
I'd be more inclined to write a chunk of code that reflects across the properties of your view model and calls a Func<string, string> to get the corresponding property name in your data model and then if that returns non-null and the property types match, call the getter on the view object and pass it to the setter on the data object.
And I would only do this if I was doing this a significant number of times.
If it's just the if that bothers you you could use the conditional operator:
channel.Part = string.IsNullOrEmpty(viewModel.Part) ?
channel.Part : viewModel.Part;
etc.
of course that always calls the set accessor for Part, which is fine unless there's logic in it (change tracking, etc.) that would be bad if it were called when the value doesn't really change.
You could also refactor the conditional operator to a method, but there's no other way to conditionally set the value without using an if.
Your code is fine. Even Jon Skeet uses if statements.
If you want the best performing code, keep it like this. If you want to make your code look pro, use any suggestion done by others here. My opinion: keep it as is.
There is absolutely nothing wrong with the code you have written.
If your objective is less lines of code, you can do this, however I think it will just add unnecessary complexity.
channel.Part = string.IsNullOrWhiteSpace(viewModel.Part) ? channel.Part : viewModel.Part;
channel.IndexName = string.IsNullOrWhiteSpace(viewModel.IndexName) ? channel.IndexName: viewModel.IndexName;
channel.MeasurementId = viewModel.MeasurementId == null ? channel.MeasurementId : viewModel.MeasurementId;
channel.Direction = string.IsNullOrWhiteSpace(viewModel.Direction) ? channel.Direction : viewModel.Direction;
Note I have switched your call from IsNullOrEmpty to IsNullOrWhiteSpace
A string with the value of " " (one or more whitespace) will get through a IsNullOrEmpty check which you probably dont want.
You can also use the coalesce operator for your nullable types (but not empty strings) like this...
channel.MeasurementId = viewModel.MeasurementId ?? channel.MeasurementId;
If those are fields and not properties, you can use something like this:
void ReplaceIfNotEmpty(ref string destination, string source)
{
if (!string.IsNullOrEmpty(source))
{
destination = source;
}
}
and then just
ReplaceIfNotEmpty(ref channel.Part, viewModel.Part);
In c# can I do something like this in a shorthand?
bool validName = true;
if (validName)
{
name = "Daniel";
surname = "Smith";
}
else
{
MessageBox.Show("Invalid name");
}
I was just wondering if something similar to this would work, but in this exact scenario, I know you can assign values if I did name = validName ? "Daniel" : "Not valid", but I was just wondering if i can do the below?
validName ?
{
name = "Daniel";
surname = "Smith";
}
:
{
MessageBox.Show("Invalid name");
}
Abusing lambda syntax and type inference:
(validName
? (Action)
(() =>
{
name = "Daniel";
surname = "Smith";
})
: () =>
{
MessageBox.Show("Invalid name");
})();
I know, not really an answer. If statement is way better: obviously this syntax is less readable and more importantly it has different runtime behaviour and could lead to unintended side effects because of potential closures created by the lambda expressions.
Syntax is a bit cryptic too. It first creates two Action objects then ?: operator chooses between them and at last the chosen result is executed:
var a1 = new Action(() => { /* if code block */ });
var a2 = new Action(() => { /* else code block */ });
Action resultingAction = test_variable ? a1 : a2;
resultingAction();
I put it together in one statement by executing the resulting action in place. To make it even briefer I cast the first lambda expression into an Action (instead of creating a new Action() explicitly) and taking advantage of type inference I left out the second cast.
No.
The ternary operator (?:) must be, as a whole, an expression -- that is, something that can be assigned to something.
Let's say you could do that. Why?
What is the motivation?
Fewer lines? not enough to make a difference.
Performance? None, the compiler will handle things for you.
Clarity? If/else is clearer and more easily understood by the majority of developers.
I am sure, if you worked hard enough, you could find a way to handle this (most likely a kludge), but I still cannot determine the why.
The conditional operator requires its second and third operands to be expressions that return a value (in addition to meeting some type restrictions) and not statements that do not resolve to a value. You have no value that you wish to return from either operation you are currently performing.
You could return some nonsensical value just for the sake of making the code compile, but at that point you're adding a ton more work than just using an if which is the correct semantic operator for your requirements, so while it is technically possible, it is not a good idea.
fullName = validName == true ? returnName(firstName)+" "+returnName(lastName) : validName == false ? invalidName("Invalid Name") : null
public string returnName(string name)
{
return name;
}
public string invalidName(string invalid)
{
MessageBox.Show(invalid);
return null;
}
As everyone else has probably said it's something you likely won't really want to do, but, it is possible :P
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Deep Null checking, is there a better way?
C# elegant way to check if a property's property is null
i have to do a lookup in a deep object model like this:
p.OrganisationalUnit.Parent.Head.CurrentAllocation.Person;
is there anyway to evalute this and return null if any of the chain is null (organizationalunit, parent, head, etc), without having to do a
if (p.org == null && p.org.Parent == null && p.org.Parent.Head . . .
You are looking for the null-safe dereference operator ?. (also known as safe navigation) that some languages (e.g. Groovy) have, but unfortunately C# does not have this operator.
Hopefully it will be implemented one day....
See also this post by Eric Lippert. The syntax he proposes there is .?.
Have you heard of the Law of Demeter?
Chaining such long sequences of calls is not a good idea. It creates awful dependencies between classes that you don't need.
In your example, the class containing p becomes dependent of five other classes. I suggest you simplify your code and make each class check for nulls at a single level, in their own context of knowledge.
Check out this article. It presents a great solution that allows you to write things like that:
p.With(x => x.OrganisationalUnit)
.With(x => x.Parent)
.With(x => x.Head)
.With(x => x.CurrentAllocation
.With(x => x.Person);
To answer the question in your title, you can avoid by applying the 'law of demeter' and creating a method called GetHeadOfParentOrganizationalUnit()
I'm not sure if the solution applies for your specific case, but it's worth a look if you can eliminate all those null checks.
See also: a link
You can use basic exception handling as well to catch that. I'm not crazy about that solution, but it is an option. If these nested nulls are normal operation, exceptions are probably not the right answer:
public class A
{
}
public class B
{
public A a;
}
public class C
{
public B b;
}
class Program
{
static A GetA(C c)
{
A myA;
try
{
myA = c.b.a;
}
catch
{
myA = null;
}
return myA;
}
static void Main(string[] args)
{
C theC = new C();
theC.b = new B();
theC.b.a = new A();
A goodA = GetA(theC);
if (goodA != null)
{
Console.WriteLine("Expected nominal path.");
}
else
{
Console.WriteLine("Unexpected nominal path.");
}
theC.b.a = null;
A badA = GetA(theC);
if (badA == null)
{
Console.WriteLine("Expected off-nominal path.");
}
else
{
Console.WriteLine("Unexpected off-nominal path.");
}
}
}