C#: reducing line noise in sanity checks [duplicate] - c#

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Shortcut for “null if object is null, or object.member if object is not null”
I wish there were a way to make this type of test simpler in C#:
if (foo != null &&
foo.bar != null &&
foo.bar.baz != null &&
foo.bar.baz.bat != null)
{
var bat = foo.bar.baz.bat;
bat.cat = 5;
bat.dog = 6;
}
One possible feature that would support this is if statements that supported new variable declarations, e.g.
if (foo != null &&
(var bar = foo.bar) != null &&
(var baz = bar.baz) != null &&
(var bat = baz.bat) != null)
{
bat.cat = 5;
bat.dog = 6;
}
The gains may not be obvious here, since the proposed solution is actually longer in this example. But with longer names it would really pay off.
Is there any better way to do this? Any chance of a suggestion like this actually making it into a future version of the language (calling Eric Lippert, come in)?

This is a fairly frequently requested feature, and as a result this question has now been asked several times on StackOverflow. See
Shortcut for "null if object is null, or object.member if object is not null"
for some thoughts on it.

Good question, but bad intentions. Your code is going to ignore the Law of Demeter

I usually just move the expression in the if-statement to its own method at the bottom of the file:
if (CheckBat(foo))
{
var bat = foo.bar.baz.bat;
bat.cat = 5;
bat.dog = 6;
}
... snip ...
private bool CheckBat(MyFoo foo)
{
return foo != null &&
foo.bar != null &&
foo.bar.baz != null &&
foo.bar.baz.bat != null;
}

Related

Why is `foo is not { } bar` not semantically equivalent to `!(foo is { } bar)`?

Let's have string foo variable in C#.
Why are the following statements not semantically equivalent?
if (!(foo is { } bar) || bar.Length == 0)
and
if (foo is not { } bar || bar.Length == 0)
For foo = null, both appear to behave identically.
var foo = null;
if (!(foo is { } bar) || bar.Length == 0)
{
Console.WriteLine("bar");
}
if (foo is not { } baz || baz.Length == 0)
{
Console.WriteLine("baz");
}
But for foo = "something", the first statement works, but the second fails with NullReferenceException.
Check sharplab.
Is it a feature?
Edit: It seems that it was a bug: https://github.com/dotnet/roslyn/issues/51996#issuecomment-803508111
From the comments on the question:
Could you be running into an issue with definite assignment? Per the docs, pattern variables are only considered definitely assigned when the is pattern is true. The changelog links to a number of git issues on the subject.
More insight from the docs:
Should we elect to defer such work until later (which I advise), we could say in C# 9 beneath a not or or, pattern variables may not be declared. Then, we would have time to develop some experience that would provide insight into the possible value of relaxing that later.

A safe way to get some deep value [duplicate]

This question already has answers here:
Elegant way to avoid NullReferenceException in C#
(4 answers)
Closed 3 years ago.
Suppose I have a fairly deep class, and I need to get some field embedded deep within
int? result = this.child.button.data;
return result;
And at any point, it could be pointing to a null, in which case I want to return null as well. A common approach would be
if (this.child != null && this.child.button!= null) {
return this.child.button.data;
} else {
return null;
}
But if the field is REALLY deep nested, then the only solution I can think of is this:
int? result = null;
try {
result = this.child.button.handler.controller.renderer.data;
} catch (NullReferenceException ex) {
// Do nothing here
}
Is this the correct approach, or is there a better solution?
you may check the null conditional operator in C# - ?.
Like:
result = this?.child?.button?.handler?.controller?.renderer?.data;

C# Cognex ,why he say null reference exception [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
enter image description here
code:
CogFindCircleLastRunRecordConstants.BestFitCircle;
CogFindCircleTool_.Run();
if ((CogFindCircleTool_.Results.GetCircle() != null) && (CogFindCircleTool_.Results.GetCircle().Visible == true))
{
cogRecordDisplay1.Record = CogFindCircleTool_.CreateLastRunRecord().SubRecords["InputImage"];
This error is because .Results is null, yet you're trying to call the GetCircle() method on it.
One way to handle this is to use the null-conditional operator (?.), which returns null if the left hand side is null, otherwise continues with the method or property on the right hand side:
// If Results is null, the call to GetCircle will not happen, and the result will be null
// Not needed on the second condition, since '&&' would return 'false' right away
if ((CogFindCircleTool_.Results?.GetCircle() != null) &&
(CogFindCircleTool_.Results.GetCircle().Visible == true))
You could shorten your code even further by adding another .? when accessing the Visible property, and then we don't need to explicitly check for .GetCircle() != null first.
Below, if Results is null or GetCircle returns null, the expression will fail (because null != true), otherwise the condition Visible == true will be evaluated:
if (CogFindCircleTool_.Results?.GetCircle()?.Visible == true)
In the comments you stated that you have a line like this inside the if statement:
Label.SetXYText(CogFindCircleTool_.Results.GetCircle().CenterX,
CogFindCircleTool_.Results.GetCircle().CenterY, "(" +
Math.Round(CogFindCircleTool_.Results.GetCircle().CenterX, 3).ToString() +
"," + Math.Round(CogFindCircleTool_.Results.GetCircle().CenterY, 3).ToString() + ")");
One thing to improve performance is to capture the result fo the GetCircle() method once rather than calling it over and over again, which takes extra processing cycles. This will also make the code shorter and more readable. You can also use string interpolation instead of concatenation to shorten the code a little more.
You also mentioned that you were still getting a null reference exception on the inner line, which could only mean that Label is null (from what I can tell). If so, we could use the ?. operator when calling the SetXYText method:
// Capture the result of GetCircle() once
var circle = CogFindCircleTool_?.Results?.GetCircle();
if (circle?.Visible == true)
{
Label?.SetXYText(circle.CenterX, circle.CenterY,
$"({Math.Round(circle.CenterX, 3)},{Math.Round(circle.CenterY, 3)})");
}
Note that the code above will not do anything if something is null. If you want to do something else if circle is null or Label is null, then you should explicitly check that rather than use the ?. operator:
if (circle == null)
{
// do something if circle is null
}
else if (circle.Visible == true)
{
if (Label == null)
{
// do something if Label is null
}
else
{
Label.SetXYText(circle.CenterX, circle.CenterY,
$"({Math.Round(circle.CenterX, 3)},{Math.Round(circle.CenterY, 3)})");
}
}

equivalent of Or in C# [duplicate]

This question already has answers here:
Equivalent of Visual Basic's And and Or in C#?
(6 answers)
Closed 8 years ago.
I have the following code:
if (bl != closeButtonLabel)
{
if (bl != minimiseButtonLabel)
{
optionPanel.Controls.Remove(bl);
}
}
Is there a way to do this in 1 if but check the 2 conditions?
At VB it's easy, you place 'Or' and not 'OrElse' but in c# there is only '||'.
Can anyone help me?
You could try the logical AND operator, '&&'.
if (bl != closeButtonLabel && bl != minimiseButtonLabel)
optionPanel.Controls.Remove(bl);
You don't need the logical Or operator here, ||.
Let's say out loud, what you want: bl should be differnt fom closeButtonLabel AND it shoud be different from minimisButtonlabel
if (bl != closeButtonLabel && bl != minimiseButtonLabel) {...}
or if you really want to use OR
if (!(bl == closeButtonLabel || bl == mimimizeButtonLabel)) {...}
(DeMorgan's Laws)
if(bl != closeButtonLabel && bl != minimiseButtonLabel)
{
//do work
}

Elegant way to check whether two Strings are different

Is there an elegant way to compare two Strings and check whether they are different? For example in Java, I usually use something similar to this:
if (text1 != text2 || (text1 != null && !text1.equals(text2))) {
// Texts are different
}
This is something so common that I was wondering maybe there is a better way.
Edit:
Ideally I want a pseudo code applicable to most common object oriented languages.
In Java 7+, you can use Objects#equals:
if (!Objects.equals(text1, text2))
Under the hood, it does something similar to the code in your question:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
Note that your code is broken in Java by the way: it will return false in this case:
String text1 = "abc";
String text2 = new String("abc");
if (text1 != text2 || (text1 != null && !text1.equals(text2))) {
System.out.println("Ooops, there is a bug");
}
The proper way to write a isNotEquals condition would be:
if (text1 != text2 && (text1 == null || !text1.equals(text2)))
Java (7 onwards):
Objects.equals(first, second);
C#:
string.Equals(first, second);
This (C#):
if(text1 != text2){
}
should do the trick as the == operator and the != operator are overloaded to do a proper string compare.
MSDN Reference
In c# personally i use the above
If(!string.IsNullOrEmpty(text1) || (!string.IsNullOrEmpty(text2) && (text1 != text2 )))
{}

Categories

Resources