I have the following if else statement inside of a foreach loop:
string date = GetDate(item)
if (date == null)
{
continue;
}
else
{
article.Date = date;
}
And I would like to write this in the concise format using ? ::
string date = GetDate(item)
date == null ? continue : article.Date = date;
From what I gather, this should work, as it is in the format condition ? first_expression : second_expression;, where first_expression is continue, however in Visual Studio 2015 I am seeing these errors for the given areas:
continue
Invalid expression term 'continue'
Syntax error, ':' expected
Invalid expression term 'continue'
; expected
:
; expected
: expected
Is it possible to use continue in this types of If/Else? If not, is there any reason for this?
https://msdn.microsoft.com/en-gb/library/ms173144.aspx
An expression is a sequence of one or more operands and zero or more operators that can be evaluated to a single value, object, method, or namespace
continue is not an expression
Your code is trying to assign continue to to your "date" variable. This doesn't make sense. I'm afraid there's no way to use the ternary operator for what you're trying to accomplish.
Well,
string date = GetDate(item)
date == null ? continue : article.Date = date;
Conditional ?: operator must return something, you can read it as:
// if(smth) { return smth} else { return smthElse; }
var result = a ? b : c;
Obviously you cannot return continue because it is not a value.
What you can do is to assign the same value if returned result is null and check it using null coalescing operator. Assuming that there are no further operations in loop this code could be refactored to something like :
article.Date = GetDate(item) ?? article.Date;
Try this one, With the default you can add default time 1/1/0001 12:00:00 AM value to your variable date if the date is null,
date == null ? default(DateTime): article.Date = date;
Related
I have two questions related to DateTime assingments
DateTime? y = 1 == 1 ? null: DateTime.MaxValue;
DateTime? y = null; // assignment works as expected
Why the first assignment issues error of type conversion between null and DateTime?
Which is the preferred way for null assignments of DateTime? in c#.
DateTime? x = default(DateTime?); //prints null on console
DateTime? x = null; // prints null on console
DateTime? x = DateTime.MinValue; //print 01/01/0001
The second statement DateTime? y = null; is only an assignment of null to a nullable object.
Whereas the first is a conditional assignment, which assigns some value for the true state and some other value for the false; Here you are using the conditional operator for evaluating the condition. according to MSDN first_expression (executes if true) and second_expression*(executes if false)* must be of same type or an implicit conversion must exist from one type to the other. In our case both are different so The simple solution is doing an explicit conversion as like this:
DateTime? y = 1 == 1 ?(DateTime?) null : DateTime.MaxValue;
A1. Because in ternary operator both expressions/results should be of same type.
Acc. to MSDN Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.
In your question, null and DateTime.MinValue do not match and hence the error conversion between null and DateTime.
You can do
DateTime? y = 1 == 1 ? null : (DateTime?)DateTime.MaxValue;
This way both answers return an answer whose type is DateTime?.
A2. Normally there is no said/preferred way of assigning this. This depends on user convention. All three are good and depend on user requirements.
Because ?: Operator operator expects same type on both sides.
Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.
So solution will be like below:
DateTime? y = 1 == 1 ? (DateTime?)null : DateTime.MaxValue;
And for second question, this will be good way for null assignment
DateTime? x = null;
DateTime? y = 1 == 1 ? null: DateTime.MaxValue;
This statement is giving an assignment error not because of the null assignment to a variable it is because of using null assignment in ternary operator and as you are using a class type here you the ternary operator do not lead you to do this illegal stuff as per CLR specifications mentioned,It might give you a straight compilation error.
//Which is the preferred way for null assignments of DateTime? in c#.
DateTime? x = default(DateTime?); //prints null on console
DateTime? x = null; // prints null on console
DateTime? x = DateTime.MinValue; //print 01/01/0001
As per Specifications and guidelines provided the Class Types should not be assigned null in any scenario so as per standard you can use the min value(though you can use default value too but it might effect in type conversions when needed)
The second one that you mentioned. You need to cast null value in this time asmensioned by Sir Nikhil Agrawal.
Ternary
int y = 1;
DateTime? dt3 = y == 1 ? (DateTime?)null : DateTime.MinValue;
Traditional way
DateTime? dt3 = null;
if (y == 1)
dt3 = null;
else
dt3 = DateTime.MinValue;
if you want to cast null to nullable datetime then you can use
DateTime? dt = (DateTime?)null;
txtNumOccupations.Text == null ? 0 : int.Parse(txtNumOccupations.Text)
cmbStatusOccupations.SelectedItem == null ? 0 : cmbStatusOccupations.SelectedItem
Error 1: Type of conditional expression cannot be determined because
there is no implicit conversion between 'int' and 'string'
If the text box is null/empty, the default value should be entered as 0 else take the text box value into int (32).
Corresponding database field is int. Thus I need to pass the int value of the text box or else pass 0 as default.
Cant assign int to a string value (txtNumOccupations.Text) or mix types in the conditional operator.
You can do:
txtNumOccupations.Text == null ? "0" : txtNumOccupations.Text;
Or
if(txtNumOccupations.Text == null) txtNumOccupations.Text = "0";
Same technique for the 2nd line:
if(cmbStatusOccupations.SelectedItem == null)
cmbStatusOccupations.SelectedItem = "0";
You might also want to use string.IsNullOrEmpty or string.IsNullOrWhiteSpace instead of comparing to null
Something like the ternary operator (?:) or the null coalescing operator (??). It seems silly to me to take up two lines and be so wordy when the other operators exist.
EDIT:
Since it's requested, here's two possible examples of what I hope that I can find
var variable ?= mightBeNull;
or
var variable = mightBeNull != null ? mightBeNull
Really, it's either something that can be used to assign a value, if it's not null, to a variable or an If without an Else packaged nicely in an operator.
The ??= operator is coming to C# 8.
int? i = null; // i = null
i ??= 0; // i = 0
i ??= 1; // i = 0
// different ways of writing 'i ??= 0;':
i = i ?? 0;
if (i == null) i = 0;
So you want this?
if (other != null)
someVariable = other;
You could do the following, but I'd argue that the above is better due to clarity and possible side effects:
someVariable = other ?? someVariable;
The above might cause side effects if someVariable is a property and either the get or set can cause side effects; this shouldn't be important if your property follows the ordinary guidelines. Or, as Servy points out, even if it's a field, it could created different semantics in a multithreaded app. I should note that in the first example, you read other twice, which also has the potential for complexity to enter (though a smaller potential than the latter example).
I bet this is what you are looking for.
Let's say we have a function, myFunction that says whether the argument passed input is null or not. If input is null, it will return "Input is null!", else it will return "Input is not null".
This is the normal approach:
public String myFunction(string input) {
if (input == null)
return "Input is null!";
else
return "Input is not null";
}
And this is the other approach (What you are looking for):
public String myFunction(string input) {
return (input == null) ? "Input is null!" : "Input is not null";
}
It is called (?: conditional operator).
To assign a value to a variable only if it is not null, you would need to use an if. Neither the conditinal nor the null coalesce operators would do that.
if(somethingElse != null) something = somethingElse;
There is no specific operator in C# that does exactly this.
In Visual Studio 2015 C# there is a new operator called the Null-Conditional that does what you are asking. It is the ?. or ? operator.
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null
int? count = customers?[0]?.Orders?.Count(); // null if customers, the first customer, or Orders is null
Currently useable in previous versions of C# but not an operator but rather a one liner would be to use the ? : statement
?: operator
condition ? first_expression : second_expression;
AssingningTO = (someVar == null) ? null: someVar; // if null assign null ELSE assign someVar
AssingningTO = (someVar == null) ? String.Empth(): someVar; // if null assign empty string else someVar
Nullable types can represent all the values of an underlying type, and an additional null value.
http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx
Possible Duplicate:
C# ?: Conditional Operator
statement first:
if(dr["AskingPriceFrom"]!=System.DBNull.Value)
objFilters.AskingPriceFrom=Convert.ToDecimal(dr["AskingPriceFrom"]);
else
objFilters.AskingPriceFrom=null;
statement second:
objFilters.AskingPriceFrom=Convert.ToDecimal(
dr["AskingPriceFrom"]!=System.DBNull.Value ? dr["AskingPriceFrom"] : null
);
What is difference between these two statements?
In first statement, if value is empty in if-else condition, then it stores null value correctly; but, if value is empty in the second condition, then instead of storing null value it stores 0. AskingPriceFrom is a get-set field stores decimal value. I tried to convert only dr["AskingPriceFrom"] after the question mark but the statement gives me an error.
Is there any way to protect null value from converting in decimal?
Apparently Convert.ToDecimal(null) == 0
//Edit: This should work
objFilters.AskingPriceFrom =
(dr["AskingPriceFrom"] != System.DBNull.Value) ?
Convert.ToDecimal(dr["AskingPriceFrom"]) : null;
It's because Decimal is not nullable. You should cast to decimal? so that when you convert a null to that type it will not return the default value 0 but instead return null.
in the inline version(ternary)
if it is null you will get:
objFilters.AskingPriceFrom = Convert.ToDecimal(null);
this will probably result an error.
You should read Convert.ToDecimal documentation here http://msdn.microsoft.com/en-us/library/e6440ed8.aspx.
Convert.ToDecimal returns decimal or throws exception, but in your case you need return type as Nullable<decimal>.
You can use code like this:
decimal? result;
if (Convert.IsDBNull(dr["AskingPriceFrom"]))
{
result= null;
}
else
{
result = dr.GetDecimal(reader.GetOrdinal("AskingPriceFrom"));
}
Thanks a lot to https://stackoverflow.com/users/1336654/jeppe-stig-nielsen. This is working properly.
objFilters.AskingPriceFrom = dr["AskingPriceFrom"] != System.DBNull.Value ? Convert.ToDecimal(dr["AskingPriceFrom"]) : (decimal?)null;
I tried to use the following example codes by using a ? b : c expression:
DateTime? GetValue(string input)
{
DateTime? val = string.IsNullOrEmpty(input) ? null : DateTime.Parse(input);
return val;
}
I got compiling error since in the a ? b : c expression because b and c are different data types; Not sure if I can use (DateTime?) case to c part?
DateTime? val = string.IsNullOrEmpty(input) ? null : (DateTime?) DateTime.Parse(input);
I would rather not use if to split this one into two or three statement.
return string.IsNullOrEmpty(input) ? (DateTime?)null : DateTime.Parse(input);
//or
return string.IsNullOrEmpty(input) ? null : (DateTime?)DateTime.Parse(input);
Either works, you have to provide some means of compatability between the two types, since DateTime cannot be null, you need to explicitly with one that you're trying to go to DateTime?, then the compiler can implicit cast the other.
The compiler is ensuring that b and c in your a ? b: c are of the same type. In your original example c is a DateTime (since DateTime.Parse returns a DateTime), and b can not be a DateTime cause its null, so the compiler says:
Type of conditional expression cannot
be determined because there is no
implicit conversion between ''
and 'System.DateTime'
You can get it to work (Because there is an implicit convertion from DateTime? to DateTime)
DateTime? val = string.IsNullOrEmpty(input) ? (DateTime?)null : DateTime.Parse(input);
But ... I think this is one of those cases where the following is much easier to follow.
DateTime? val = null;
if (!string.IsNullOrEmpty(input)) {
val = DateTime.Parse(input);
}
With the caveat that the whole premise of the function is pretty risky, you are only failing early sometimes.
The method has very odd semantics! It will fail with an exception if an invalid date format is passed in unless it is null or an empty string. This violates the fail early principle.
Did you actually try it? Yes it works. Go grab LINQPad to try little things like this.
LINQPad is more than just a LINQ tool: it's a highly ergonomic code snippet IDE that instantly executes any C#/VB expression, statement block or program – the ultimate in dynamic development. Put an end to those hundreds of Visual Studio Console projects cluttering your source folder!
I just tried
public static DateTime? GetValue(string input)
{
DateTime? val = string.IsNullOrEmpty(input) ? null : (DateTime?)DateTime.Parse(input);
return val;
}
and it worked fine.
Use this:
DateTime? val = string.IsNullOrEmpty(input) ? null : new DateTime?(DateTime.Parse(input));
Edit:
The other answers will work too, but with this syntax you won't even need casting.