Null coalescing operator vs. value() - c#

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;
}

Related

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

return statement that checks the first two characters before proceeding

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;

Multiple inline comparison while assigning values to object properties

I am working on c# data model class, I created instance and assigning values from another object. I am aware of single line comparision but I need multiple, I have tried && operator but compiler complain 'invalid opperator'. I am sure what I am missing, surly it must be simple!
var answerDataModel = new AnswerDataModel()
{
Id = answerId,
//need help to
Value = AnswerDtoObject.Answers.FirstOrDefault() == null? &&
isSubQuestionExist == true ? "_SBQA"
: AnswerDtoObject.Answers.FirstOrDefault(),
};
if I remove "&& isSubQuestionExist == true ?", then code works
You have an errant ? operator. Just combine your comparisons in a single conditional operator:
Value = (AnswerDtoObject.Answers.FirstOrDefault() == null && isSubQuestionExist == true) ?
"_SBQA" :
AnswerDtoObject.Answers.FirstOrDefault()
Value = (AnswerDtoObject.Answers.FirstOrDefault() == null) &&
(isSubQuestionExist == true) ? "_SBQA"
: AnswerDtoObject.Answers.FirstOrDefault(),

NullReferenceException using where clause

I have a scenario that I am getting the result properly .But i have to search it in that result.Here is my code.
if(productSearch.Keyword !=null || productSearch.Code!=null)
{
var key = productSearch.Keyword;
var cod = productSearch.Code;
if (productSearch.Code != null)
{
var Selected_Result = result.Results.Where(s => s.Code.ToLower().Contains(cod.ToLower())).ToList();
result.Results = Selected_Result;
}
else
{
var Selected_Result = result.Results.Where(s => s.Keyword.ToLower().Contains(key.ToLower())).ToList();
result.Results = Selected_Result;
}
}
But it gives following exception :
Object reference not set to an instance of an object on result.Results.Where(s => s.Code.ToLower().Contains(cod.ToLower())).ToList();
I know s => s.Code.ToLower() is coming NULL, but i dont know why, result has records.
Thanks in advance.
If it's null in the query then chances are it's null in the DB. To be on the safe side you can use the null coalescing operator to make sure you have at least something to call ToLower on e.g.
result.Results.Where(s => (s.Code ?? "").ToLower().Contains(cod.ToLower()))
.ToList();

Why Task doesn't return null

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;

Categories