What does ?? operator means in C#? [duplicate] - c#

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What do two question marks together mean in C#?
Hi, I was looking for some trainings of MVC 2 in C# and I found this sintax:
ViewData["something"] = something ?? true;
So, what is that '??' means ?.

It's the null-coalescing operator.
It returns the first argument unless it is null, in which case it returns the second.
x ?? y is roughly equivalent to this (except that the first argument is only evaluated once):
if (x == null)
{
result = y;
}
else
{
result = x;
}
Or alternatively:
(x == null) ? y : x
It is useful for providing a default value for when a value can be null:
Color color = user.FavouriteColor ?? defaultColor;
COALESCE
When used in a LINQ to SQL query the ?? operator can be translated to a call to COALESCE. For example this LINQ query:
var query = dataContext.Table1.Select(x => x.Col1 ?? "default");
can result in this SQL query:
SELECT COALESCE([t0].[col1],#p0) AS [value]
FROM [dbo].[table1] AS [t0]

It is the null coalescing operator. The return value is the left hand side if it is non-null and the right hand side otherwise. It works for both reference types and nullables
var x = "foo" ?? "bar"; // "foo" wins
string y = null;
var z = y ?? "bar"; // "bar" wins
int? n = null;
var t = n ?? 5; // 5 wins

If something is null, it returns true, otherwise it returns something.
See this link for more.

Related

Ternary operator add or not where conditions in linq

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();

C#: How do I use a method, check if return is null, and set value in one line using lambda and C# Null Propagation

Is this possible in one line of code ? null : yourHelpfulAnswer
Thank you in advance.
var x = await Foo_Get() == null ? 123: Foo.SomeProperty;
Just seems like there is a much better way than:
var myVal = 123;
var foo = await Foo_Get();
if(foo != null) myVal = foo.SomeProperty;
That should do the trick:
var myVal = (await Foo_Get())?.SomeProperty ?? 123;
Simplified:
? = if value on left is null use null, otherwise use property
?? = if value on the left is null use the value on the right instead.
You can use the null coalescing operator to set myVal:
var myVal = (await Foo_Get())?.SomeProperty ?? 123;

getting a formatted nullable date string in a LINQ query

This really seems like it should be working:
var result = (from x in Db.RebateDetail
where batch != null && batch != "" ? x.BatchNumber.Value == Convert.ToInt32(batch) : x.DatetimeCreated.Date >= Convert.ToDateTime(fromDate).Date && x.DatetimeCreated.Date <= Convert.ToDateTime(toDate).Date
select new
{
id = x.Id,
batchNumber = x.BatchNumber,
firstName = x.FirstName,
checkDate = x.CheckDate.Value.ToString("MM/dd/yy") ?? "",
checkNumber = x.CheckNumber
}).ToList();
The checkDate errors out with 'Nullable object must have a value.'
Is that not what the ?? should be doing?
I have tried several variations on this but cannot seem to make it happy.
Update: This is using Entity Framework and LinqToEF
Currently, "if CheckDate is null" it would yield a System.InvalidOperationException rather than take the value on the RHS of the ?? operator hence the error "Nullable object must have a value".
You'll need to ensure that either the LHS returns a value or the RHS does.
What you're looking for is the conditional operator ?:
checkDate = x.CheckDate.HasValue ?
x.CheckDate.Value.ToString("MM/dd/yy") : string.Empty

Why does using LINQ change properties when used in if

when I use someList.Where(t => t.isTrue = true) nothing happens. But when I use code as given below,
if(someList.Where(t => t.isTrue = true).Count() > 0)
return;
All items inside the list are set to true. Why this is happening?
Edit : I am not trying to assign or compare anything. I am curious about why this happens when used with if.
This happens because you use an assignment instead (=) of equality compare (==).
Also it only happens when you use Count because LINQ only evaluates the lambda expression when it has to get a value.
var q = someList.Where(t => t.isTrue = true); // Nothing will happen
q.ToList() // would happen here
if(q.Count() > 0 ) { .. } // Also here
To compare and not assign the value you should use:
var q = someList.Where(t => t.isTrue == true);
var q = someList.Where(t => t.isTrue); // Or simpler
The reason the compiler allows this is because assignment is an expression that has a value. For example :
int a = 10;
int b;
int c = (b = a) ; // (a=b) is of type int even though it also assigns a value, and b and c will have a value of 10
In your case, the assignment of a bool has type bool, which happens to be a valid return value for a lambda passed to Where
All items inside the list are set to true when you use = and then evaluates the expression by using Count().
As the isTrue is a boolean this would be enough to count the values which is true
if(someList.Where(t => t.isTrue).Count() > 0)
return;
As an alternative to checking if the count is higher than 0 you can use the Any method which already does just that
if(someList.Where(t => t.isTrue).Any()) // Any returns true if there are any elements in the collection
return;
You can further simplify this with an overload of Any that takes the condition as a parameter, skiping the additional Where
if(someList.Any(t => t.isTrue)) // This overload takes a function that returns a boolean like Where does and returns true if there is at least 1 element that matches the condition
return;

Null coalescing operator vs. value()

I'm creating some objects to return to a form via API, and the objects are derived from database values, including values that could be null in the database, but cannot be null in the context of my API (I am obtaining data from multiple tables, so I know that if a field is null in one table, I can obtain a legitimate value from another table):
List<ResultsByLineShiftSlot> returnResults = new List<ResultsByLineShiftSlot>();
foreach (LineShiftSlot ls in db.LineShiftSlots.OrderBy(ls => ls.ScheduledDateAndTime).Where(ls => ls.ProductionDate == slotDate &&
ls.ShiftId == shiftId &&
ls.LineId == lineId &&
ls.Quantity > 0 &&
ls.BlendId != null))
{
var recordedResult = db.LineShiftSlotResults.FirstOrDefault(r => r.LineShiftSlotId == ls.Id);
if (recordedResult != null)
{
ResultsByLineShiftSlot returnResult = new ResultsByLineShiftSlot
{
BlendId = recordedResult.BlendId
};
}
else
{
ResultsByLineShiftSlot returnResult = new ResultsByLineShiftSlot
{
BlendId = ls.BlendId ?? 0
};
}
}
return returnResults;
In the above example, BlendId can be null in LineShiftSlots, but not in LineShiftSlotResults.
In this context where a nullable variable is known to contain a non-null value, which is better?
Should I use the null coalescing operator:
BlendId = ls.BlendId ?? 0
Or should I use .Value():
BlendId = ls.BlendId.value()
Both compile, and seem to work.
Are they functionally equivalent in this context? Is using one over the other better practice? I know that .value() could potentially return an exception, whereas the null coalescing operator could not, but in this case .value can never be null.
In the general case, they're not semantically equivalent.
labelId = recordValue.labelId.Value;
This one means I know the value can't be null. Just throw if my assumption is wrong.
On the other hand,
labelId = recordValue.labelId ?? 0;
labelId = recordValue.labelId.GetValueOrDefault();
These two mean that the value may be null, and if that happens, just ignore it, considering it's normal, and substitute it with the default value.
I'd use GetValueOrDefault() in that case, it makes it somewhat more obvious (and the JIT will inline this method).
However, your code is equivalent to this simpler alternative:
labelId = recordValue.labelId ?? otherValue;
In this case the code would be the same however have you considered the following
labelId = recordValue.labelId ?? otherValue
which is essentially the following
if(recordValue.labelId != null){
labelId = recordValue.labelId.Value;
}
else
{
labelId = otherValue;
}

Categories