简体   繁体   中英

Inline conditional c# - next best solution?

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.

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

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("");

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).

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

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?);

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("") 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM