Streamwriter.Write Doesn't Write to File; No Exception Thrown

Why doesn't the C# ternary operator work with delegates?

The problem is that demo1 is not a simple expression, it is a method. And methods can be overriden, so it is not actually one method, it is a method group. Consider the following example:

public class Demo {
protected bool branch;
protected void demo1 (int) {}
protected void demo1 () {}
protected void demo2 () {}
public Action DoesntWork() {
return branch ? demo1 : demo2; //Error
return demo1; //ok
}
}

Now, demo1 is overloaded, so which one of the two versions should be used? The answer is that the overloaded function is selected by using the context in which the function is used.

In the return demo1 it is obvious, it expects an Action.

But in the return branch? demo1 : demo2; the context is not so easy. The ternary operator first tries to match the type of demo1 with that of demo2, but that is another method group so there is no help there. The compiler does not look beyond and fails.

The solution is to make clear the type expected from the method group:

return branch? new Action(demo1) : demo2;

return branch? (Action)demo1 : demo2;

Action d1 = demo1;
return branch? d1 : demo2;

Conditional operator and Comparison Delegate

Th error method actually says it all but it’s not quite intuitive. If you use a method name without invoking the method, you are handling a method group. “group”, because a method could be overloaded and the name can indicate any of the overloaded methods.

Now, method groups are convertible implicitly to a delegate with matching signature, this is why your assignment in if works.

So far, so good. However, the conditional operator ?: needs to deduce a common type to which its second and third arguments can be implicitly converted, and it does not consider all conversions for that (this would have diverse problems). It merely looks whether both arguments have the same type, or whether one is implicitly convertible into the other.

This is not the case here: although both arguments are method groups, they are in fact different method groups with distinct types, and you cannot convert one method group into another. Even though both can readily be converted into a delegate, the compiler forbids this usage.

The same is true for other types, by the way:

object = someBool ? "" : New List<Integer>();

also fails to compile, for the same reason. And again, we can make this compile by explicitly casting either of the arguments to a common base type:

object = someBool ? (object) "" : New List<Integer>();

Action returning void and taking parameter, with ternary operator

You'll need to cast one side or other - or not use the conditional operator.

Basically, ignore the assignment - because the compiler does. It doesn't use the fact that you're trying to assign to a variable to work out the type of the conditional expression. We're left with just:

(i > 5) ? action1 : action2

as the expression. What's the type of that? What delegate type should the method groups be converted to? The compiler has no way of knowing. If you cast one of the operands, the compiler can check that the other can be converted though:

(i > 5) ? (Action<PerformanceCounterCategory>) action1 : action2

Alternatively:

Action<PerformanceCounterCategory> action = action2;
if (i > 5)
{
action = action1;
}

It's unfortunate, but that's life I'm afraid :(

Does the null-conditional operator function the same with delegates and regular objects?

In this answer, Eric Lippert confirms that a temporary variable is used in all cases, which will prevent the "?." operator from causing a NullReferenceException or accessing two different objects. There are, however, many other factors which can make this code not thread safe, see Eric's answer.

UPD: to address the claim that a temporary variable is not created: there is no need to introduce a temp variable for a local variable. However, if you try to access something that may conceivably be modified, a variable gets created. Using the same SharpLab with slightly modified code we get:

using System;
using System.Collections.Generic;

public class C {
public List<Object> mList;

public void M() {
this.mList?.Add(new object());
}
}

becomes

public class C
{
public List<object> mList;

public void M()
{
List<object> list = mList;
if (list != null)
{
list.Add(new object());
}
}
}

Exception of casting of delegates in a ternary expression

Use calcul = (moyenneAnnee < moyenneBac) ? (CalculerMoyenneGenerale)CalculerSansVightcinq : CalculerAvecVightcinq;

Selecting a function with ternary conditional operator

Func<T1,T2,T3,TResult> should do it

private int function1(int x, int y, int z) => 1;
private int function2(int x, int y, int z) => 2;

private void main(string[] args)
{
bool condition = true;
Func<int, int, int, int> func = condition ? function1 : function2;
func(1, 2, 3);
}

It's two statements though, not sure if it's possible to do it in one like you ask.

Method Call using Ternary Operator

The reason why the above statement does not work was provided by the other users and effectively did not answer my true question.

After playing around some more, I figured out that you CAN use this operator to do the above statement, but it results in some bad code.

If I were to change the above statement to;

int a = 5;
int b = 10;
int result = a == b ? doThis() : doThat();

private int doThis()
{
MessageBox.Show("Did this");
return 0;
}
private int doThat()
{
MessageBox.Show("Did that");
return 1;
}

This code will compile and execute the way it should. However, if these methods were not originally intended to return anything, and referenced other areas in the code, you now have to handle a return object each time to call these methods.

Otherwise, you now can use a ternary operator for a one-line method chooser and even know which method it called in the next line using the result.

int result = a == b ? doThis() : doThat();

if (result == 0)
MessageBox.Show("You called doThis()!");

Now, this code is absolutely pointless and could be easily done by a If Else, but I just wanted to know if it could be done, and what you had to do to get it to work.

Now that I know that you can effectively return any type in these methods, this might become a little more useful. It may be considered a "Bad Coding Practice" but might become very useful in situations it was never MEANT for.

You could get access to one object or another based on any condition and that might be very useful in one line of code.

UserPrivileges result = user.Group == Group.Admin ? GiveAdminPrivileges() : GiveUserPrivileges();

private UserPrivileges GiveAdminPrivileges()
{
//Enter code here
return var;
}
private UserPrivileges GiveUserPrivileges()
{
//Enter code here
return var;
}

Sure, this can be done by an If Statement, but I think that using the Ternary Operator for other uses makes programming fun. Now, this may not be as efficient as an If Else statement, in which case, I would never use this.

Difference between ternary (conditional) operator and if statement returning an Action

Why explicit cast is required in Conditional operator

_doSomething = ThisOrThat ?  DoThis : DoThat; 

From this answer from Jon Skeet:

as the expression. What's the type of that? What delegate type should
the method groups be converted to? The compiler has no way of
knowing
. If you cast one of the operands, the compiler can check
that the other can be converted though

For your question:

Why it is allowed in if statement

You are doing a simple assignment where left hand side is Action and the right hand side is a method group. There exists implicit conversion

See Assignment Operator(=) C#

The assignment operator (=) stores the value of its right-hand operand
in the storage location, property, or indexer denoted by its left-hand
operand and returns the value as its result. The operands must be of
the same type (or the right-hand operand must be implicitly
convertible to the type of the left-hand operand
)



Related Topics



Leave a reply



Submit