I have a valid if: else; code section as follows:
var obj = new Object();
if(Validation.IsDirectory(fileName))
{
obj = Activator.CreateInstance(typeof(FilePath));
}
else
{
obj = Activator.CreateInstance(typeof(FileName));
}
The above generates no error. But, if I translate this to a shorthand if statement, like below:
Validation.IsDirectory(fileName) ? obj = Activator.CreateInstance(typeof(FilePath)) : obj = Activator.CreateInstance(typeof(FileName));
I get the error:
Error CS0201 Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
In that error documentation it clearly states that:
...Invalid statement is any line or series of lines ending in a
semicolon that does not represent an assignment (=), method call (),
new, -- or ++ operation.
But out of my first 3 statements the first is a method call and the last two are assignment operations.
So, why am I receiving this error? And how do I write this statement as a shorthand if statement?
You cannot make the assignment inside the ternary operator. This operator is used in expressions and yields a value that you then can assign. Also, since now we have a single assignment, we can merge this with the declaration.
(Btw., the initialization expression new Object() in your declaration is superfluous, as the following statements replace this object anyway. object obj; would suffice.)
object obj = Validation.IsDirectory(fileName)
? Activator.CreateInstance(typeof(FilePath))
: Activator.CreateInstance(typeof(FileName));
However, you can simplify this further and call the Activator only once by applying the ternary operator the Type arguments only:
object obj = Activator.CreateInstance(
Validation.IsDirectory(fileName) ? typeof(FilePath) : typeof(FileName)
);
It would be easier to work with FilePath and FileName if they had a common base class that you would use instead of object. The same pattern is used in the System.IO Namespace namespace with the DirectoryInfo Class and the FileInfo Class. Both derive from System.IO.FileSystemInfo and share common members like Name, FullName or Delete().
The ternary conditional operator is not "a shorthand if statement". The ternary operator is an expression which resolves to a value.
In your attempt it would be structurally similar to a line of code which is nothing more than a value:
4;
This line of code is not a statement, hence the error.
You can use the result of the expression as part of a statement. For example:
var x = 4;
Or in your case:
var x = someTernaryExpression;
Which would be:
var obj = Validation.IsDirectory(fileName) ? Activator.CreateInstance(typeof(FilePath)) : Activator.CreateInstance(typeof(FileName));
In short...
When you want to conditionally perform an operation, use if.
When you want to conditionally resolve to a value inline, use ?:.
You perform the assignment as a result of (i.e. after) the ternary operator
obj = Validation.IsDirectory(fileName) ? Activator.CreateInstance(typeof(FilePath)) : Activator.CreateInstance(typeof(FileName));
The ternary operator does the check and returns the first value when true, otherwise it returns the second value.
The returned value can then be assigned normally.
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;
}
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);
In C# I know you can do things like this:
int number = true ? 1 : 0;
This returns the left or right side depending on if the Boolean is true or not.
But is there a way to do the same thing but instead run a function instead of returning a value? Something like this:
This doesn't work (I get multiple syntax errors)
WPS.EDIT_MODE ? ExecuteEditMode() : ExecutePublicMode();
Thanks.
The conditional operator must return a value. Assuming the functions don't both return a meaningful value for you, you should use an if statement to do that:
if(someCondition)
doA();
else
doB();
Although technically you could use an anonymous function to do this if you really wanted:
int number = someCondition ?
new Func<int>(() => { doA(); return 0; })() :
new Func<int>(() => { doB(); return 1; })();
but that's not suggested; using an if/else is both easier and more readable for that case.
If both functions return an int, yes.
The ternary operator is about returning values. Not returning values doesn't make sense.
The conditional operator (?:) returns one of two values depending on
the value of a Boolean expression.
http://msdn.microsoft.com/en-us/library/ty67wk28(v=vs.80).aspx
Suppose you are using the ternary operator, or the null coalescing operator, or nested if-else statements to choose assignment to an object. Now suppose that within the conditional statement, you have the evaluation of an expensive or volatile operation, requiring that you put the result into a temporary variable, capturing its state, so that it can be compared, and then potentially assigned.
How would a language, such as C#, for consideration, implement a new logic operator to handle this case? Should it? Are there existing ways to handle this case in C#? Other languages?
Some cases of reducing the verbosity of a ternary or null coalescing operator have been overcome, when we assume that we are looking for direct comparisons, for example. See Unique ways to use the Null Coalescing operator, in particular the discussion around how one can extend the usage of the operator to support String.IsNullOrEmpty(string). Note how Jon Skeet is using the PartialComparer from MiscUtil, to reformat 0s to nulls,
Why is this possibly necessary? Well, take a look at how we write a comparison method for complex objects without any shortcuts (examples from the cited discussions):
public static int Compare( Person p1, Person p2 )
{
return ( (result = Compare( p1.Age, p2.Age )) != 0 ) ? result
: ( (result = Compare( p1.Name, p2.Name )) != 0 ) ? result
: Compare( p1.Salary, p2.Salary );
}
Jon Skeet writes a new comparison to fallback the equality case. This allows the expression to extend by writing a new specific method which returns null, allowing us to use the null coalescing operator:
return PartialComparer.Compare(p1.Age, p2.Age)
?? PartialComparer.Compare(p1.Name, p2.Name)
?? PartialComparer.Compare(p1.Salary, p2.Salary)
?? 0;
The null coalescing operator is more readable because it has two sides, not three. The boolean condition clause is separated into a method, in this case returning null if the expression must be continued.
What would the above expression look like if we could more easily put the condition in-line? Take the expression from PartialComparer.Compare which returns null, and place it in a new ternary expression which allows us to use the evaluation of the left-side expression, with an implicit temporary variable value:
return Compare( p1.Age, p2.Age ) unless value == 0
: Compare( p1.Name, p2.Name ) unless value == 0
: Compare( p1.Salary, p2.Salary );
The basic "flow" of an expression would be:
expression A unless boolean B in which case expression C
Rather than being an overloaded comparison operator, I suppose this is more like a short-circuiting inverted ternary operator.
Would this type of logic be useful? Currently the null coalescing provides us a way to do this with the conditional expression (value == null).
What other expressions would you want to test against? We've heard of (String.IsNullOrEmpty(value)).
What would be the best way to express this in the language, in terms of operators, keywords?
personally I'd avoid the short circuit from operators and just let the methods chain it:
public static int CompareChain<T>(this int previous, T a, T b)
{
if (previous != 0)
return previous;
return Comparer<T>.Default.Compare(a,b);
}
use like so:
int a = 0, b = 2;
string x = "foo", y = "bar";
return a.Compare(b).CompareChain(x,y);
can be inlined by the JIT so it can perform just as well as short circuiting built into the language without messing about with more complexity.
In response to your asking whether the above 'structure' can apply to more than just comparisons then yes it can, by making the choice of whether to continue or not explict and controllable by the user. This is inherently more complex but, the operation is more flexible so this is unavoidable.
public static T ElseIf<T>(
this T previous,
Func<T,bool> isOK
Func<T> candidate)
{
if (previous != null && isOK(previous))
return previous;
return candidate();
}
then use like so
Connection bestConnection = server1.GetConnection()
.ElseIf(IsOk, server2.GetConnection)
.ElseIf(IsOk, server3.GetConnection)
.ElseIf(IsOk, () => null);
This is maximum flexibility in that you can alter the IsOk check at any stage and are entirely lazy. For situations where the is OK check is the same in every case you can simplify like so and entirely avoid extensions methods.
public static T ElseIf<T>(
Func<T,bool> isOK
IEnumerable<Func<T>[] candidates)
{
foreach (var candidate in candidates)
{
var t = candidate();
if (isOK(t))
return t;
}
throw new ArgumentException("none were acceptable");
}
You could do this with linq but this way gives a nice error message and allows this
public static T ElseIf<T>(
Func<T,bool> isOK
params Func<T>[] candidates)
{
return ElseIf<T>(isOK, (IEnumerable<Func<T>>)candidates);
}
style which leads to nice readable code like so:
var bestConnection = ElseIf(IsOk,
server1.GetConnection,
server2.GetConnection,
server3.GetConnection);
If you want to allow a default value then:
public static T ElseIfOrDefault<T>(
Func<T,bool> isOK
IEnumerable<Func<T>>[] candidates)
{
foreach (var candidate in candidates)
{
var t = candidate();
if (isOK(t))
return t;
}
return default(T);
}
Obviously all the above can very easily be written using lambdas so your specific example would be:
var bestConnection = ElseIfOrDefault(
c => c != null && !(c.IsBusy || c.IsFull),
server1.GetConnection,
server2.GetConnection,
server3.GetConnection);
You've got lots of good answers to this question already, and I am late to this particular party. However I think it is worthwhile to note that your proposal is a special case of a more generally useful operation which I dearly wish C# had, namely, the ability to in an expression context, give a name to a temporary computation.
In fact C# has this operator but only in query comprehensions. I wish we had been able to add this as an operator in C# 3:
public static int Compare(Person p1, Person p2) =>
let ages = Compare(p1.Age, p2.Age) in
ages != 0 ?
ages :
let names = Compare(p1.Name, p2.Name) in
names != 0 ?
names :
Compare(p1.Salary, p2.Salary);
"Let expressions" are one of those expressions that are so useful, and found in so few languages, and I genuinely do not understand why language designers do not add it immediately in version one.
If C# had this feature then your proposed:
A() unless B() : C()
is simply
let a = A() in B() ? C() : a
which is hardly more difficult to understand, and bonus, you get to use a in expressions B() and C() if you like.
Let expressions can be emulated in any language that has lambdas; of course let x = y in z is simply (x=>z)(y), but there is no concise way to write that in C# either because C# requires a conversion to a delegate type on every lambda.
Incidentally, in Roslyn we do not represent temporaries as let-expressions, though we could. Rather, we go even one level below that and have a representation for "sequence of operations that might produce values, one of which will become the value of this expression". "let x = y in z" is simply the sequence "allocate x, x = y, z, deallocate x" where the third element is the value. And in the original pre-roslyn C# compiler we had internal operators "left" and "right", which were binary operators that took two expressions and produced either the left or right side, so we could generate ((allocate x) right ((x = y) right z)) left (deallocate x).
My point here is: we often get requests for bespoke language features with unusual punctuation, but it would in general have been better to implement the basic building blocks that you could build these operators out of in a natural way.
To place one proposed implementation away from a very verbose question, let's run with the unless keyword.
(expression A) unless (boolean B) <magical "in which case" operator> (expression C)
... would be all there is to it.
Boolean expression B would have access to the evaluation of expression A through the keyword value. Expression C could have the unless keyword in its expression, allowing for simple, linear chaining.
Candidates for the <magical "in which case" operator>:
:
|
?:
otherwise keyword
Usage of any symbols tend to diminish readability for the average developer. Even the ?? operator is not used widely. I, myself, do prefer to develop verbose code, but that I can easily read one year from now.
So a candidate for your :
expression A unless boolean B in which case expression C.
would be
expression A unless boolean B sothen expression C.
Although many people like me would still use:
if (B) {expression C;}
else {expression A;}
This comes in when you are developing a software with a big team, with different backgrounds, each one on the team master of one language, and just user of others.
More #ShuggyCoUk: Ah, I see that this might work for more than just comparisons? I haven't used C# 3 and extension methods, but I suppose you can declare, for my previous example, below, a
public delegate bool Validation<T>( T toTest );
public static T Validate<T>( this T leftside, Validation<T> validator )
{
return validator(leftside) ? leftside : null;
}
Followed by, per Skeet:
Validation<Connection> v = ( Connection c ) => ( c != null && !( c.IsBusy || c. IsFull ) );
Connection bestConnection =
server1.GetConnection().Validate( v ) ??
server2.GetConnection().Validate( v ) ??
server3.GetConnection().Validate( v ) ?? null;
Is this how that would work in C#? Comments appreciated. Thank you.
In response to ShuggyCoUk:
So this is an extension method in C# 3, then? Also, the result here is an int, not an arbitrary expression. Useful for overloading yet another comparison method. Suppose I wanted an expression for choosing the best connection. Ideally, I want something to simplify the following:
Connection temp;
Connection bestConnection =
( temp = server1.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull) ? temp
: ( temp = server2.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull ) ? temp
: ( temp = server3.GetConnection() ) != null && !(temp.IsBusy || temp.IsFull ) ? temp
: null;
Ok, so one could have a method
bool IsOk( Connection c )
{
return ( c != null && !(c.IsBusy || c.IsFull) );
}
Which would produce:
Connection temp;
Connection bestConnection =
( temp = server1.GetConnection() ) && IsOk( temp ) ? temp
: ( temp = server2.GetConnection() ) && IsOk( temp ) ? temp
: ( temp = server3.GetConnection() ) && IsOk( temp ) ? temp
: null;
But how would method chaining for comparisons work, here? I am pondering something which looks like:
Connection bestConnection =
server1.GetConnection() unless !IsOk(value) otherwise
server2.GetConnection() unless !IsOk(value) otherwise
server3.GetConnection() unless !IsOk(value) otherwise null;
I think that there are so far, hoops to jump through, if I want the result of a conditional to be an expression or result of a method which was in the original conditional.
I assume that the object returned by such methods will be expensive to produce, or will change the next time the method is called.