This question already has answers here:
How to find out if a file exists in C# / .NET?
(6 answers)
Closed 6 years ago.
I am wanting to check if a file exists, if it does do nothing if it does not copy over a file. This is the code I have, but I get compile errors such as
Only assignment, call increment, decrement and new object expressions can be used as a statement
Invalid expression return
Invalid expression term ':'
; Expected
This is the syntax I have
string template = "C:\\Test\\database12.mdb";
string dest = "R:\\Production\\database12.mdb";
if (File.Exists(dest) ? return : File.Copy(template, dest));
The conditional operator (? :) is an operator that returns a value and can't be used to control program flow. Use a standard if-else instead:
if (File.Exists(dest))
return;
else
File.Copy(template, dest);
Which can be simplified to:
if (File.Exists(dest))
return;
File.Copy(template, dest);
or just
if (!File.Exists(dest))
File.Copy(template, dest);
assuming there's nothing after the file copy.
You're using a Conditional Operator to specify then/else behaviour, which is not valid.
The ?: operator is for getting a value depending on a bool. Thus you should be getting an object frm a pair of options with the same type.
When you want logic to branch, you need to use an if statement, the synatx for which is
if(condition)
{
// Do true stuff here
}
else
{
// Do false stuff here
}
The conditional operator
var result = x ? y : z;
can be seen as a shortcut for something like
T result;
if (x)
result = y;
else
result = z;
with T being the type of both y and z. This makes clear that y and z must resolve to values (and not statements) of the same type so the entire statement has a consistent type.
This also makes clear that you can not simply use any method call for y or z, but only such method calls that result in values of the same type.
So while it is ok to write
var value = condition ? func1() : func2(someValue);
as long as func1 and func2 are methods returning values of the same type, it is not ok to write
var value = condition ? return : null;
return is not a value and you may not use return as one of the operands in the conditional operator. You may not even do this:
var value = condition ? return true : false;
You could even do something like this:
if ((File.Exists(dest) ? CalcFileSize(dest) : 0) > 0)
{
// Do something if the file exists and it has content
}
It's far easier (and correct) in this case to simply use the good old if:
if (File.Exists(dest))
return;
File.Copy(template, dest);
Related
C# provides conditional operator (?:) that returns one of two values depending on the value of a Boolean expression. eg
condition ? first_expression : second_expression;
My question is can we use the same syntax to call a method when condition is true? and when condition is false then do nothing
public void Work(int? val)
{
var list = new List<int>();
//ofcourse line below doesn't work
//but is it possible to call method when condition is true and else do nothing
val.HasValue? list.Add(val.value) : else do nothing
}
the ?: has also been referred to as the ternary operator in the past. Ternary, for three. if this, then do this, else do this.
You have two expressions. If this, do this. This is exactly the point of an if statement. You are trying to fit your case into a construct that it isn't designed for. Don't do this.
Use the correct operation for the job:
if(val.HasValue)
{
list.Add(val.value)
}
The C# conditional operator is used to return a different value depending on the evaluation of a condition. It is not meant to be used to to be used the way you are trying to in your question. It should like be used this :
int test = i > 3 ? 0 : 1;
test will then equal 0 if i is less than (or equal to) 3, or test will equal 1 if 3 is greater than 3.
To do what you want you will have to use a regular if statement (which you can still write in one line by the way) :
if (val.HasValue) list.Add(val.value);
The conditional/ternary operator is supposed to return a value and that very specific value must be assigned back to somewhere.
So, in that case you can do that, yes. But, it would lead to bad design.
In a regular case, one would do this:
int x = (a > b) ? a : b;
Now, lets assume AddToList() is your desired method when the condition renders to true and DoRest() is the method you want to invoke if the condition turns out to false.
In the aforementioned case, you'd end up doing something like this:
int result = val.HasValue? AddToList(val.value) : DoRest();
Now you have to rely on result for finding out which one has been called (if you ever need that) and it's not very expressive and doesn't point to proper code design.
If you get a tad more adventurous you'd end up with :
var actionToInvoke = val.HasValue ? (Action)AddToList: (Action)DoRest;
actionToInvoke();
In any case, none of these lead to very readable code.
So, sticking with a simple if(val.HasValue) would be the simplest way to go here.
The way null conditional operator works is you have to return a value for the variable you are assigning it to. So if you would like a string value or something else other than void you can call the method with out any problem. But to call a void method you can use a delegate.
delegate void DelMethod();
void Method() { }
void MethodTwo() { }
private void MyMethod()
{
DelMethod x;
x = condition == true ? (DelMethod)Method : (DelMethod)MethodTwo;
}
I want replicate this condition:
string responseText = getData();
if(responseText == null){ return; }
with the ternary operator, what I tried is:
responseText == null ? return : null;
but I get return underlined in red with:
return is not a valid term for the expression.
Essentially I want stop the code of this function with a return if responseText is null, instead if is different against null I need to continue my code. What I did wrong?
Ternary operator is used for assignment:
string a = isEmpty ? item : null; //this is OK
If you assign nothing, you cannot use the ternary operation.
response == null ? return : null; //what is this??
What you have done, is likely already correct:
if (responseText == null)
return;
//do something else when text is not null
The purpose of a ternary operator is to be able to create an expression that uses conditions.
It's not intended for controlling the flow of your program, and you shouldn't attempt to use it that way.
Stick with your if statement.
The ternary operator is an expression - it returns one value or the other based on the condition. You are trying to use it for program flow which is not possible.
I see nothing wrong with your if statement - is it clear, concise, and most importantly, it works.
You can't return return. The returned value must be a variable of the same type as the one receiving the ternary expression's result.
The ternary operator evaluates an expression. It cannot control the flow of your program. Your best bet is to use an old fashioned if statement, such as the one you provided in your question.
The operand of a ternary operator should be a expression yielding a value. But in this case return doesn't yields any value.
I want to use the ?: operator intstead of if else
e.g.
var directory = new DirectoryInfo(path);
if (!directory.Exist())
{
directory.Create();
}
else
{
// do nothing
}
I tried to use ?: like this:
var directory = new DirectoryInfo(path);
!directory.Exist() ? directory.Create() : void;
but it says "Invalid expression term void", null also isn't working.
Can anyone tell me a solution?
In you scenario, only having a if condition is better suited.
Just for your understanding, A ternary Operator (?:) needs to result into a value in the right side and also needs a variable in left side to assign the result value e.g.:
x = (y== null) ? 0: 1;
This means assign 0 to x when y is null otherwise assign 1.
So in your example/scenario, you may write something like this to result into a directory creation status as below:
var newDirectoryCreated = (!directory.Exist()) ? directory.Create() : false;
This way, if new directory is created then newDirectoryCreated will assigned with true otherwise false.
Simply keep the if statement and remove the else clase since you aren't doing anything in there.
You're trying to use the ternary operator which, by definition, must return a value.
From the documentation:
The conditional operator (?:) returns one of two values depending on the value of a Boolean expression.
If your just looking for brevity, you could try this instead:
if (!directory.Exist())
directory.Create();
Ternary operator are not designed to replace if/else They are to simplify assignment and declaration. It should be able to assign the result the statement to something like variable or function. There major use are in assignment or reading.
Something like
var status = !directory.Exist() ? directory.Create() : false;
The correct solution would be to stick to native if condition. The following is enough:
var directory = new DirectoryInfo(path);
if (!directory.Exist())
{
directory.Create();
}
The ?: operator's behavior is roughly this:
for x ? y : z, it will return y if x is true, and otherwise it will return z.
From this we can deduce a couple of things:
both y and z must return something (it won't work if either of them evaluate to void), and
y and z must evaluate to the same type. (Imagine you had something like this: var r = x ? y : z;. Which type is r? Is it the type of y or z? We don't know which of them will be returned, but we have to pick a type at compile-time. So they have to return the same type.
In your case, both evaluate to void, which doesn't work. (And if you changed the last part to null, as you said you'd tried, then they evaluate to different types, one of which is void, which breaks both rules)
The conditional operator (?:) musts return one of two values depending on the value of a Boolean expression. So you can stick with if clause instead, it is still simple to understand rather than conditional operator:
var directory = new DirectoryInfo(path);
if (!directory.Exist()) directory.Create();
The ?: operator is an extention of the if-then-else construction.
The extention is in the then-block and the else-block. Where the then-block and the else-block return void for the if-then-else construciton it must return a type for the ?: operator. An aditional constraint for the types in the ?: operator is that the two types must be identical. This constraint is softened a bit by the fact that automatic casting will be used by the compiler to make the two types identical.
Code using ?: operators is in general shorter but also harder to read. This is one point to consider when replacing the if-then-else construct with the ?: operator. Unless your then-block and else-block are one liners it seldom is worth replacing it with the ?: operator.
The if-then construction is a limited version of the if-then-else construction (or visa versa, the if-then-else construction is an extention of the if-then construction). Since the if-then construction has only one code block, the then-block, it is not possible to replace the if-then construction with the ?: operator. You first have to extend the if-then construct with an empty else-block.
Examples:
// initialising an integer with an if-then construct.
int x = 0;
if (some_condition)
{
x = 1;
}
Think of this as if the then-blockreturns an integer.
It is not possible to use the ?: operator strait away.
// initialising an integer with an if-then-else construct.
int y;
if (some_condition)
{
y = 1;
}
else
{
y = 0;
}
Extended the if-then construct to a if-then-else construct and think of the then-block and else-block as returning a integer for witch the types coincidently ;-) match with each other.
It is possible to use the ?: operator in this case.
// initialising an integer with a ?: operator.
int z = (some_condition) ? 1 : 0;
About your code:
var directory = new DirectoryInfo(path);
if (!directory.Exist())
{
directory.Create();
}
In this case I do not see a sensible way to make the then-block returning a value. That makes using the ?: operator impossible or highly complicated with ugly code as a result. My advise, stick to the if-then construct in this case.
Is there any difference between below two statements
if (null != obj)
and
if (obj != null)
If both treated same which will be preferable?
The first is a Yoda condition. Use it you should not.
The difference here is the code generated. The two will not generate the exact same code, but in practice this will have no bearing on the results or performance of the two statements.
However, if you create your own types, and override the inequality operator, and do a poor job, then it will matter.
Consider this:
public class TestClass
{
...
public static bool operator !=(TestClass left, TestClass right)
{
return !left.Equals(right);
}
}
In this case, if the first argument to the operator is null, ie. if (null != obj), then it will crash with a NullReferenceException.
So to summarize:
The code generated is different
The performance and end results should be the same
Except when you have broken code in the type involved
Now, the reason I think you're asking is that you've seen code from C, which typically had code like this:
if (null == obj)
Note that I switched to equality check here. The reason is that a frequent bug in programs written with old C compilers (these days they tend to catch this problem) would be to switch it around and forget one of the equal characters, ie. this:
if (obj = null)
This assigns null to the variable instead of comparing it. The best way to combat this bug, back then, would be to switch it around, since you can't assign anything to null, it's not a variable. ie. this would fail to compile:
if (null = obj)
No, but the second way is more common and more readable (and more logical in my opinion)
No, there is not. It's exactly the same.
The style null == obj is sometimes just used to prevent the common typo obj = null to not accidently assign null to a variable, but with != there's absolutely no reason to do so.
In .NET it won't actually compile for the typo obj = null.
So the compiler prevents you from accidently doing it.
The Yoda condition comes originally from other languages, where this compiler feature is missing.
They are exactly the same.
Some people prefer to put the null as the first part of the expression to avoid errors like this
if (obj = null) // should be obj == null
But of course this doesn't apply to the != operator, so in your example it's just a difference of style.
First type of statement came from C/C++, where was possible to pass not boolean values to condition verification. E.g. anything not 0 was true, and zero was false:
if (5) { } // true
if (0) { } // false
Sometimes it created problems if you forgot to type one '=' char:
if (x = 5) { } // this was true always and changed x value
if (x == 5) { } // this was true, if x was equal to 5
So, Yoda syntax was used, to receive compiler error in case one '=' was missed:
if (5 = x) { } // this was generating compiler error for absent-minded programmers
if (5 == x) { } // this was true, if x was equal to 5
C# allow only boolean value in conditions, So
if (x = 5) { } // this won't compile
if (x == 5) { } // this is true, if x was equal to 5
What about boolean types?
if (y = true) { }
if (y == true) { }
Well, this is useless code, because you can just write if (y).
Conclusion: Yoda syntax is gone with C/C++ and you do not need to use it anymore.
The use of the first form
if (blah == obj)
stems from the days when compilers would not catch if (obj = blah) i.e. unintentional assignment, unless compile warning level was set to maximum
It seems the compiler is not going let this syntax fly.
void main()
{
foo(false?0:"");
}
void foo(int i) {return;}
void foo(string s) {return;}
The only other way I can see of fixing this is something as follows:
void bar(object o)
{
if (o is string){//do this}
else{//im an int, do this}
}
Anyone have any better ideas?
You cannot use a method with a void return type in a ternary expression in this way. End of story.
To understand why this is, remember what the ternary operator actually does -- it evaluates to the following:
(condition ? [true value] : [false value])
What this implies is that the following code:
int x = a ? b : c;
Must be rewritable to:
int x;
if (a)
{
x = b;
}
else
{
x = c;
}
The two above are logically identical.
So how would this work with a method with void as its return type?
// Does this make sense?
int x = condition ? foo(s) : foo(i);
// Or this?
if (condition)
{
x = foo(s);
}
else
{
x = foo(i);
}
Clearly, the above is not legal.
That said, others' suggestions would otherwise be valid if only your foo overloads returned a value.
In other words, if your signatures looked like this:
object foo(string s);
object foo(int i);
Then you could do this (you're throwing away the return value, but at least it'll compile):
object o = condition ? foo(0) : foo("");
Anyway, the ol' if/else is your best bet, in this case.
The method call of foo is determined at compile time, so it cannot call a different method (or overload) based on the result of evaluating the condition. Instead, try something like this:
condition ? foo(0) : foo("")
This way, the compiler will succeed in performing overload resolution and will resolve the first call to foo(int) and the second call to foo(string).
EDIT: As noted by other, you cannot use the ?: operator as a statement, nor can you use methods which return void in it. If your actual methods return compatible types, you could do something like:
int result = condition ? foo(0) : foo("");
If not, you must use an if:
if (condition)
foo(0);
else
foo("");
You're example doesn't make a whole lot of sense (the second example doesn't relate to the first).
I think the first example would be fine as:
void main()
{
foo("");
}
Since 0 will never be passed anyway (false is always false) and you can't use the inline conditional operator without an assignment somewhere (which your example is lacking).
As for the second way, that is probably how I would prefer to see it:
void bar(object o)
{
if(o is string) foo(o as string);
else foo((int)o);
}
I wouldn't pass in an object as a parameter. The int will be boxed, which is a little less efficient. Let the compiler figure out which method to call.
If you wrote:
foo(0);
foo("");
The appropriate method would be called. You could also write:
if (condition) {
foo(0);
} else {
foo("");
}
Depending on what you're trying to do (your example is lacking in a little detail).
If you use Inline if expressions in C#, both parts before and after the ":" have to be of the same type. What you are intending would never work.
Even if you like to do something like this:
DateTime? theTime = true ? DateTime.Now : null;
The compiler is not satisfied. In this case you will have to use:
DateTime? theTime = true ? DateTime.Now : default(DateTime?);
The conditional operator needs the true and false part to be of the same type. Which is why it's not compiling.
var x = condition ? 0 : "";
What type should the compiler choose for x? If you really want it to choose object make a cast or you could force it to choose dynamic in which case method overload would still work but you loose type safety. Both are however strong smells.
Having to test the runtime type is usually a design error but with the limited code (that will always have the same result) it's hard to help with a different approach that would require testing on runtime types
This:
foo(false?0:"")
Could be this:
false ? foo(0) : foo("")
Both results of the conditional operator must of the same type (or be implicitly convertible). So foo(false ? 0 : "") won't work because it is trying to return an Int32 and a String. Here's more information on the conditional operator.
The fix I would do is change that line to false ? foo(0) : foo("").
EDIT: Derp, can't use a conditional operator just in the open like that. They can only be used for assignments. You'll have to use a if/else block. Not in one line, but it'll do in a pinch.