Any tips on how to fix this code smell (not my code):
Id = blah== null ? null : something.x ? null : something.y
Is perlish writing considered beneficial in C#? is using multiple lines and being clear a bad thing? How the hell is anyone to read the above? it is has takes 2 "if"s to assign a value.
Is there cleaner way of dealing with above?
In this case, another alternative to consider would be:
Id = (blah == null || something.x) ? null : something.y;
The benefit being that only one ternary is necessary (and thus null is returned from only one "branch" out of two, rather than two out of three).
This is ternary operator, For clear understanding you can convert it into if..else condition
Like,
if(blah == null)
{
Id = null;
}
else
{
if(something.x)
Id = null;
else
Id = something.y;
}
In your case ternary operator is used twice, so it might look confusing. Syntax of ternary operator is
condition ? consequent : alternative
It seems hard to read, but you could put each condition and statements in a line, it could be more easy to read.
Id = blah== null //Condition
? null //Then
: something.x //Condition
? null //Then
: something.y //Else
Related
What is the fastest way (in terms of minimizing the amount of code statements) to get a property from an object after checking that the object isn't null?
string s = null;
if (null != myObject)
{
s = myObject.propertyName;
}
For reference: Wait for future C# 6.0 feature for null checking with possible ?. syntax:
string result = obj?.ToString();
For now: Use ternary operator:
string result = obj != null ? obj.ToString() : null;
C# does not have a null-propagating operator (although it has been discussed a few times). Frankly, "faster" is not likely to be a factor here, as it will typically end up in the same (or similar enough) IL, but I tend to use:
string s = myObject == null ? null : myObject.PropertyName;
the situation you describe is only one scenario where the operator is useful. It's also handy to replace constructs like this:
if (value != null)
{
return value;
}
else
{
return otherValue;
}
Or
return value != null ? value : otherValue;
with
return value ?? otherValue;
Well, I have the following query that I use to search a LIST with the text that the user has filled.
It's only one textbox that search in all these fields below, it's working but when one of these fields is null, it's throwing a null reference exception, how can I avoid that?
List<REP_MEDIDORDISPLAY> SearchFiltered = new List<REP_MEDIDORDISPLAY>();
if (filter != String.Empty)
{
SearchFiltered.Clear();
foreach (String Item in filter.Split(';').ToList<String>())
{
SearchFiltered.AddRange(Medidores.Where(x => x.Data_TOI.Contains(Item.Trim()) ||
x.Elemento.ToUpper().Contains(Item.Trim()) ||
x.Fase.ToUpper().Contains(Item.Trim()) ||
x.ID.ToUpper().Contains(Item.Trim()) ||
x.KdKe.ToUpper().Contains(Item.Trim()) ||
x.N_Equipamento.ToUpper().Contains(Item.Trim()) ||
x.Status.ToUpper().Contains(Item.Trim()) ||
x.Tensao.ToUpper().Contains(Item.Trim())));
}
}
I hope you guys can help me. thanks.
By checking for null first:
(x.Elemento != null && x.Elemento.ToUpper().Contains(Item.Trim())) ||
// etc
Of course you should also calculate Item.Trim() just once and reuse this value for all tests rather than trimming as many times as there are fields.
You can add null check to each of the properties. Example:
From
x.Fase.ToUpper().Contains(Item.Trim()) ||
To
(x.Fase != null && x.Fase.ToUpper().Contains(Item.Trim())) ||
Maybe you should introduce something like a null object. This object is empty and will therefore always return false on every query against it.
If you implement nullchecks for every property on that object your code will rot over time. And you are gonna have a bad time.
There are many ways to do what you are doing, some more elegant perhaps.
One simple way could be to override the ToString method in the object in the Medidores sequence and use that for the comparison.
Something like this:
class Medidor {
... properties
public override string ToString() {
return Data_TOI + Elemento ... etc
}
}
And then you could compare against that instead.
SearchFiltered.AddRange(
Medidores.Where(x =>
x.ToString()
.IndexOf(Item.Trim(), 0, StringComparison.InvariantCultureIgnoreCase) != -1
);
I'm using IndexOf as it has an overload that takes StringComparison.InvariantCultureIgnoreCase, which ignores casing among other things.
The reason why I think this approach is preferred to what you have now, is that the Meridor object itself is responsible for what fields are included in the ToString method. Maybe it can improve readability and maintainability.
a ?? b
If a is not null => returns a.
Else (a is null) => returns b.
I want to simulate something like its inverse (AFAIK there is no operator to do this):
If a is null => return a.
Else (a is not null) => returns b.
The idea is that b would be the result of a function that receives a and needs to avoid null parameters. Like this: a XX fn(a) where XX would be the operator (if it exists).
My only two variants are:
a == null ? a : fn(a)
a == null ? null : fn(a)
Is there any way to simplify this code?
Not sure exactly what you're trying to accomplish? Something like this?
TResult NullFn<TParam, TResult>(TParam a, Func<TParam, TResult> method)
{
if(a == null) return null;
return method(a);
}
...
var result = NullFn(a, a => fn(a))
But the best solution IMHO would be to just have fn return null if it is passed a null value.
EDIT:
The method at the top is only an example. You might want to use something like this in a situation where you've got a LOT of the same operation over and over again in a specific area and you can't change fn because it would make is easier to focus on the rest of the code and there's a chance you might want to alter the null-handling behavior for all your operations at once in the future. (I'm assuming that is the case because you're asking in the first place.) But I wouldn't use this across an entire application because it isn't clear what's happening if you don't have the NullFn function right in front of you.
Whats wrong with simple condition?
if (a != null) b = fn(a);
Another option - add a condition to your method:
public B fn(A a)
{
if (a == null)
return null;
return new B();
}
Personally I would prefer
(a != null) ? fn(a) : null
because I think it makes the intention more obvious, but I can not think of a way to simplify that much. You could use an extension method if you like.
a.CallIfNotNull(fn)
with the following extension method
internal static T CallIfNotNull<T>(this T value, Func<T, T> function)
where T : class
{
return (value != null) ? function(value) : null;
}
Not really better but probably less error prone and easier to type given IntelliSense.
(Is assumed the function returns a value of the same type as the argument as the question suggests.)
If you have T a; and T fn(T a); using the same user-defined type T, then you can write a && fn(a) and it will expand to T.False(a) ? a : T.&(a, fn(a)).
You've answered your own question with the ?: implementations at the bottom.
The only improvement i would suggest is to wrap the functionality in a method that makes it cleaner and less error prone to do.
object SafeB(object a)
{
return a==null ? a : b(a);
}
The compiler will probably inline this so you won't lose performance.
You may even be able to implement it as an extension method of the class that provides b so that it becomes an even more integrated solution.
I have a class with a string property. I use the coalesce operator when reading from it as it might be null, but it still throws me an NullRefrenceExeption.
string name = user.Section.ParentSection.Name ?? string.Empty;
To be more specific, its the ".ParentSection" that's null so is it because it don't even have ".name" ? If that's the case should i test ".ParentSection" first with an if block?
I assume there are something about the Coalesce operator i dont understand, hope someone can shed some light on whats going wrong here.
To be more specific, its the ".ParentSection" that's null so is it
because it don't even have ".name" ?
Yes.
If that's the case should i test ".ParentSection" first with an if
block?
Yes.
You'll need to check if Section and ParentSection are null. You could use an if-statement for this or write an extension method like this:
public static class MaybeMonad
{
public static TOut With<TIn, TOut>(this TIn input, Func<TIn, TOut> evaluator)
where TIn : class
where TOut : class
{
if (input == null)
{
return null;
}
else
{
return evaluator(input);
}
}
}
You would use this method like so:
string name = user.With(u => u.Section)
.With(s => s.ParentSection)
.With(p => p.Name) ?? string.Empty;
I think it's a lot cleaner than an if-statement with a lot of &&.
Some further reading: http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad
You need to check if user, user.Section, or user.Section.ParentSection are null before you can use the null coalescing operator on a property of user.Section.ParentSection.
Nested property access is not safe if any of the objects accessed are null this will throw a NullReferenceException. You will have to explicitly test for the outer objects to be not null.
E.g.:
string name = string.Empty;
if(user!=null && user.Section!=null && user.Section.ParentSection !=null)
name = user.Section.ParentSection.Name ?? string.Empty;
In general I would try to avoid nested access to properties, you are violating the Law of Demeter. Some refactoring might make this unnecessary in the first place.
The ?? operator checks if the left side is null and if so returns the right one, if not the left one.
In your case the left-side is the "Name" property in the object user.Section.ParentSection and this is null.
In those cases either think on what might be null or do something like this:
string name = user == null
|| user.Section == null
|| user.ParentSection == null
|| user.Section.ParentSection.Name == null
? string.Empty
: user.Section.ParentSection.Name;
(yeah it's ugly I know)
Chances are user or user.Section or user.Section.ParentSection is a null value.
The ?? operator doesn't prevent checks like:
if (user != null && user.Section != null && user.Section.ParentSection != null){
Make sure that everything up to the string property is valid and exists, then you can use ??. You can't call (null).Name, no matter how many times you try.
Yes you need to check if Section or ParentSection are null before you check Name
It is probably best to do something like this:
if(user!=null && user.Section!=null && user.Section.ParentSection!=null)
{
string name = user.Section.ParentSection.Name ?? string.Empty;
}
The null coalescing operator takes a statement like:
a = b ?? c;
What this says is "evaluate b; if it has a non-null value then assign that to a. Otherwise assign the value of c to a".
However within your b you're using a user object which may be null that has a section object that may be null that has a parent section property that may be null that had a name property that may be null. If you wanted to check all of these (and typically you should) then you can do something like:
string name = string.Empty;
if (user != null &&
user.Section != null &&
user.Section.ParentSection != null)
{
name = user.Section.ParentSection.Name ?? string.Empty;
}
As soon as the IF check fails it will not check further and therefore you don't get a NullReferenceException when you assume an object is present and then try to access one of its properties.
Simple LINQ query:
from transport in db.Transports
select new
{
Current = transport.CurrentLocation,
CurrentCarriers = transport.CurrentLocation.Carriers,
};
Problem: CurrentLocation may be null. If it is, executing this query throws a NullReference. I tried adding a check like
transport.CurrentLocation == null ? null : transport.CurrentLocation.Carriers
but Linq to sql does not seem to be able to parse that.
Any nice solutions that do not involve sending an extra query for each transport?
I normally just use 'let'.
from x in Foo
let y = x.Bar
where y != null
select y.Baz;
UPDATE:
I think the ?? operator does translate to SQL.
If the foreign key on Transports is nullable, you'll have to check that column for null before you can try and get the CurrentLocation object.
You could do something like this:
CurrentLocation = transport.currentLocationId != null ? transport.CurrentLocation : null;
Just do (you where using the wrong property):
transport.CurrentLocation == null ? null : transport.CurrentLocation.Carriers
Update 1: That is weird, I have used some pretty complex queries and didn't face that issue. I just checked one, don't think it matters, but mine had the check inverted:
transport.CurrentLocation != null ? transport.CurrentLocation.Carriers : null;
Can you post the complete query you tried that gives you the parse exception?