This is how I get my sum
double? myVar = myList.Sum(x => x.MyItem);
Is-it possible to replace myVar with null if .Sum() return 0 in the same line ?
I don't want to use
if(myVar == 0) myVar = null;
Does LINQ have a post-conditional statement ?
It sounds like you want the reverse of the null-coalescing operator, and there's nothing in either LINQ or the C# language to do that for you. You could create your own extension method to do that if you wanted though:
public T? NullIfDefault<T>(this T? value) where T : struct
{
if (value == null)
{
return value;
}
return EqualityComparer<T>.Default.Equals(default(T), value.Value)
? null : value;
}
Then:
double? myVar = myList.Sum(x => x.MyItem).NullIfDefault();
(There are various other options for how you code NullIfDefault, e.g. using Nullable<T>.GetValueOrDefault() - you might want to play around to find the form you like most.)
Related
I have this query:
if(!string.IsNullOrEmpty(code) && !string.IsNullOrEmpty(name))
{
return this.context.Table.Where(
x => EF.Functions.Contains(x.Code, $"\"{code}\"")
&& EF.Functions.Contains(x.Name, $"\"{name}\""));
}
else if(string.IsNullOrEmpty(code) && !string.IsNullOrEmpty(name))
{
return this.context.Table.Where(x => EF.Functions.Contains(x.Name, $"\"{name}\""));
}
else
{
return this.context.Table.Where(x => EF.Functions.Contains(x.Code, $"\"{code}\""));
}
I tried to do it again using the ternary operators then check if the string is not null or empty and if so add the where clause or not
I tried such a thing but obviously expects that after the "?" there is the alternative of ":"
return this.context.Table.Where(
x => !string.IsNullOrEmpty(code)
? EF.Functions.Contains(x.Code, $"\"{code}\"")
&& !string.IsNullOrEmpty(name)
? EF.Functions.Contains(x.Name, $"\"{name}\""));
Since unlike the example in my case I have to check 8 different input parameters that if not passed must not be used in the where for the controls, I wanted to avoid filling the code of many if cases and rewriting the query n times for the different combinations, is there a way or should I resign myself?
You can just return true for any you don't want to check for like below
!string.IsNullOrEmpty(code) ? EF.Functions.Contains(x.Code, $"\"{code}\"") : true;
This means if the string is null or empty then it will return true which should provide the behaviour you're expecting.
Do not use ternary operators for combining query. EF will create non optimal SQL.
Usually such task is done in the following way:
var query = this.context.Table.AsQueryable();
if (!string.IsNullOrEmpty(code))
{
query = query.Where(
x => EF.Functions.Contains(x.Code, $"\"{code}\""));
}
if (!string.IsNullOrEmpty(name))
{
query = query.Where(
x => EF.Functions.Contains(x.Name, $"\"{name}\""));
}
var result = query.ToList();
Simple version
var myVar = some object;
myList.Where(element => myVar != null && element.Name == myVar.Name)
What I want to write
public static (Return Value) Start<T>(this T input, Func<(IDK what goes here)> exp)
{
var theVar = somehow get the myVar that was passed in;
if (theVar != null)
{
apply exp; <= I can do this part
}
}
myList.Start((myVar, element) => element.Name == myVar.Name));
Basically be able to write an expression without having to check for the null every single time.
Use anonymous lambda (I think without testing) >
myList.Start((myVar, () => element) => element.Name == myVar.Name));
I found a way, i wrote a class BaseExtension it doesn't have a lot in it, just a holder for some properties
public static BaseExtension<T> Start<T, TValue>(this IQueryable<T> input, TValue value, Func<TValue, Expression<Func<T, bool>>> expression) =>
new BaseExtension<T>(input, value == null ? null : expression.Invoke(value));
this allows me to write
_context.MyEntities.Start(myVar, value => entity => entity.Id.ToString() == myVar)
and passing in myVar allows me to do c# logic behind the scenes before the query would be executed in the database.
An example would be myVar != null or I can add a custom function that would apply the expression or not
The where method expected a Boolean type, you can use this
private static <type> <name>(<type> arg)
{
return true;
}
If this not work for you, on Visual Studio, writing something insidere where, and press ctrl + . .
See the sugested implementations
return ship.DefenseType?.PropulsionMethod != null
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
Hi, my current return statement, above, is returning a Propulsion method if it's not null. However, my database has different types of
propulsion methods denoted by the first 2 letters in the field(PK, PA, PT, etc).
How can I check to make sure that the PropulsionMethod starts with "PK" before going further into the return statement?
In pseudo code, it might look something like this:
if (ship.DefenseType?.PropulsionMethod).startsWith("PK")
&& ship.DefenseType?.PropulsionMethod != null)
{
return new BattleMethod(ship.DefenseType.PropulsionMethod)
}
else
{
return null;
}
I tried
return ship.DefenseType?.PropulsionMethod != null &&
ship.DefenseType?.PropulsionMethod.StartsWith("PK")
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
But I get this error:
operator && cannot be applied to operands of type bool and bool?
Just add this condition too:
return ship.DefenseType?.PropulsionMethod != null
&& ship.DefenseType?.PropulsionMethod.StartsWith("PK")
? new BattleMethod(ship.DefenseType.PropulsionMethod) : null;
As the operator is && so the second condition will be evaluated if the first one was true (not null in this case).
You can compare nullable bool directly with true:
return ship.DefenseType?.PropulsionMethod?.StartsWith("PK") == true
? new BattleMethod(ship.DefenseType.PropulsionMethod)
: null;
I want to create an if/else statement in this case :
var controls= _listControls
.Select(
control => new
{
Name,
Quantity,
Valid = isValid
? sp.GetInfos(ID).SerialNumber.ToString()
: string.Empty
})
.ToList();
I just want to check if sp.GetInfos(ID).SerialNumber.ToString()is null in the statement and say if it's not null ? DoThings() : DoThings() .
Thanks
You can use ternary operators inside other ternary statements like this
Valid = isValid
? string.IsNullOrEmpty(sp.GetInfos(ID).SerialNumber?.ToString())
? string.Empty
: sp.GetInfos(ID).SerialNumber.ToString()
: string.Empty
N.B. The SerialNumber?.ToString() is a null conditional operator, you can read more about it here
You can encapsulate all logic in a helper method. As I consider it's more readable and also you are able to test this method separately.
string Valid(....)
{
if (isValid)
{
if (sp.GetInfos(ID).SerialNumber == null)
{
....
}
else
{
..
}
}
return string.Empty;
}
And then simply call this method inside LINQ query
var controls = _listControls
.Select(
control => new
{
Name,
Quantity,
Valid = Valid (...)
})
.ToList();
I'm working with the new Task Parallel Library and today went to this case:
This code doesn't compile:
internal Task<Guid?> SavePages(string[] pages)
{
return Task.Run(() =>
{
if (pages == null || pages.Length == 0)
return null;
....
Unless I explicitly returns a null nullable Guid:
internal Task<Guid?> SavePages(string[] pages)
{
return Task.Run(() =>
{
if (pages == null || pages.Length == 0)
return (Guid?)null;
// Check documents path access
Why this behavior, I'm I doing something wrong? I mean, I get the code to work with the second option but don't know If I'm misusing the library, I mean, null is always null, isn't it?
Compile error:
Cannot convert lambda expression to delegate type
'System.Func' because some of the return
types in the block are not implicitly convertible to the delegate
return type
http://msdn.microsoft.com/en-us/library/dd460717.aspx
This has to do with the way the compiler determines the type of your lambda. When you return a plain null, the only thing the compiler can imply is that you are returning an object. Hence, your parameterless lambda is compatible with Task<object>. However, the signature of your function says that you are returning Task<Guid?>, so the return type the compiler implied from your code is not compatible. When you cast that null to Guid?, you provide the compiler a the clue it is missing to make the lambda a Task<Guid?>.
This is a limitation with type inference in the C# compiler. This issue is not unrelated to the one involving the ternary operator:
int? num = a != null ? a.Value : null; // Will not compile
int? num = a != null ? a.Value : (int?)null; // Compiles
int? num = a != null ? (int?)a.Value : null; // Compiles
Another workaround for your specific situation is to specify the generic type explicitly:
return Task.Run<Guid?>(() =>
{
if (pages == null || pages.Length == 0)
return null;