How to assign the ResourceDictionary string as switch case Constant Expression? - c#

switch ("Case2")
{
case (string)Application.Current.FindResource("Case1");
//Do Some logic
break;
case (string)Application.Current.FindResource("Case2");
//Do Some logic
break;
case (string)Application.Current.FindResource("Case3");
//Do Some logic
break;
default:
break;
}
I did this code But it is not work. Now i want to assign the string value((string)Application.Current.FindResource("Case1")) which getting from resource dictionary to constant expression.How is it possible or else is there any way ?

It is not possible. A constant expression is, by definition, a compile-time constant. A resource dictionary lookup must happen at run time. The usual solution is to use a string of if statements:
if ("Case2" == (string)Application.Current.FindResource("Case1"))
{
//Do some logic
}
else if ("Case2" == (string)Application.Current.FindResource("Case2"))
{
//Do some logic
}
else if ("Case2" == (string)Application.Current.FindResource("Case3"))
{
//Do some logic
}

Related

C# Case which include other cases

How to execute in one case, other cases? I could just copy paste those other cases, or put it to some external function but there is so much code so I dont want to do that.
Example:
switch(foo)
{
case 3:
{
//something
}break;
case 4:
{
//something else
}break;
case 5:
{
//here i want to execute case 3 and case 4
}break;
}
I think that this was previously answered but I can't find how to do it.
C# doesn't have such functionality. You have to create other methods which will do actions for cases 3 and 4 and call them from case 5 branch. I would suggest to create a separate class FooHandler which would handle your value. It's easily extendable and readable.
public class FooHandler
{
private readonly int _foo;
public FooHandler(int foo)
{
this._foo = foo;
}
public void Handle()
{
switch(this._foo)
{
case 3: this.HandleCase3(); break;
case 4: this.HandleCase4(); break;
case 5: this.HandleCase5(); break;
default: throw new ArgumentException("Foo value is invalid");
}
}
private void HandleCase3()
{
// Your code for case 3
}
private void HandleCase4()
{
// Your code for case 4
}
private void HandleCase5()
{
this.HandleCase3();
this.HandleCase4();
}
}
Usage:
var fooHandler = new FooHandler(foo);
fooHandler.Handle();
If you don't want to add methods (you didn't explain why),
you can use Action local variables holding Lambda expressions.
In the example below you can replace the body of the lambdas with whatever code you have for "something" and "something else".
Action also supports passing arguments to the lambda's body if you need them.
Action something = () => { Console.WriteLine("something"); };
Action something_else = () => { Console.WriteLine("something_else"); };
switch (foo)
{
case 3:
something();
break;
case 4:
something_else();
break;
case 5:
something();
something_else();
break;
}
You could also change the switch to two ifs:
if (foo == 3 || foo == 5)
{
//something
}
if (foo == 4 || foo == 5)
{
//something else
}
It would be easier to use if-statements. Here I also used pattern matching to simplify the tests.
if (foo is 3 or 5) {
// something
}
if (foo is 4 or 5) {
// something else
}
So simple and easy to read and understand.
I would argue that the code being intuitive is important; hence, I would suggest defining helper variables that clarify intention.
While not knowing the meaning of 3, 4 and 5, a hypothetical example could be:
var awesomeFoos = new[] { 3, 5 };
var popularFoos = new[] { 4, 5 };
var fooIsAwesome = awesomeFoos.Contains(foo);
var fooIsPopular = popularFoos.Contains(foo);
if (fooIsAwesome)
{
// something (preferably refactored to a separate method)
}
if (fooIsPopular)
{
// something else (preferably refactored to a separate method)
}
, where .Contains() is found in the System.Linq namespace.
An example fiddle is found here.
That being said, though; you seem quite determined that you would prefer to keep your code as-is, to an as large extent as possible. If that is really a high priority, you could consider putting the whole foo-switch logic inside a method and let it call itself twice in the case 5 scenario:
private static void HandleFoo(int foo)
{
switch(foo)
{
case 3:
{
// something
}break;
case 4:
{
// something else
}break;
case 5:
{
HandleFoo(3);
HandleFoo(4);
}break;
}
}
Example fiddle is found here.
(Depending on the content of // something and // something else, this may not be feasible, though.)
I strongly recommend changing the way you want to implement this statement. This method is not suitable for modern applications and is coupled with everything. But if you need to implement as you asked, You can jump between cases by using goto.
For more information Read "jump statements".
int a = 10;
switch (a)
{
case 0:
//Condition1:
//some actions
break;
case 1:
goto case 0;
//or
goto Condition1;
break;
default:
break;
}
Since this is the linear approach you should check conditions in if for each goto in each case(cause you can't Go back to each step)
Another approach is to save all cases in the order you want to execute and run the switch multiple times. I use a while in my example you can use goto if you don't want to use a loop.
Queue<int> cases = new Queue<int>();
//1 is the main switch value
cases.Enqueue(1);
while (cases.Count > 0)
{
int temp = cases.Dequeue();
switch (temp)
{
case 0:
Console.WriteLine("0");
break;
case 1:
Console.WriteLine("1");
cases.Enqueue(3);//run case 3
cases.Enqueue(0);//then run case 0
break;
case 2:
Console.WriteLine("2");
break;
case 3:
Console.WriteLine("3");
break;
default:
break;
}
}

C# switch comparison

I'm trying to learn programming C# (self taught) and I came to a point where I don't know if switch case can be used like if condition.
Can I make a comparison with switch like this?
switch(var)
{
case var < 10:
//Do something
break;
}
Or this is a case of why if condition is different compared to switch?
Certain comparisons can be done in switch cases via patterns. In your specific scenario, a relational pattern could check if a switch input is < 10.
switch(var)
{
case < 10:
//Do something
break;
}
One significant limitation of patterns is that the values inside them have to be constant. So if you had a variable int x and tried to use it in case < x: it wouldn't work.
https://dotnetcoretutorials.com/2020/08/10/relational-pattern-matching-in-c-9/
Deciding if to use an IF statement or SWITCH statement depends on a number of factors, including the readability of your code. There are times when multiple IF statements provide a more simpler approach than using switch. Other times it would be best to use a switch statement.
The simple answer to your question is yes but it would be best for you to try both in a particular scenario if you want to learn.
For most purposes switch is an alternative way to write an chain of if/else statement
switch(myVar)
{
case 1:
//Do something
break;
case 2:
//Do something
break;
case 3:
//Do something
break;
default:
//Do something else
}
Is equivalent to
if(myVar == 1) {
//Do something
}
else if(myVar == 2) {
//Do something
}
else if(myVar == 3) {
//Do something
}
else {
//Do something
}
In older versions of C# (pre 7.0) case statements were restricted to only testing if values were equal to a constant. However with the introduction of a feature called 'pattern matching' you can do more expressive matches within case statements. Subsequent C# versions have added more and more syntax in this area, but ultimately they don't do anything beyond what can be achieved with an if/else chain. For situations where there are a lot of conditions the switch/case statements are typically easier to read
An example of changes in syntax being allowed C# 9.0
switch(myVar)
{
case == 1:
//Do something
break;
case > 1 and < 3:
//Do something
break;
case == 3:
//Do something
break;
default:
//Do something else
}

Why does the compiler add statements to the switch?

I have the following reasonably simple switch statement.
// earlier
string fullPath = GetFullPath();
string type = GetEntityType();
switch (type.ToLower()) {
case "tables":
tables.Add(fullPath);
break;
case "views":
views.Add(fullPath);
break;
case "functions":
functions.Add(fullPath);
break;
case "storedprocs":
storedprocs.Add(fullPath);
break;
case "data":
data.Add(fullPath);
break;
case "layouts":
layouts.Add(fullPath);
break;
case "scripts":
scripts.Add(fullPath);
break;
default:
Console.WriteLine($"What is this: {type}");
break;
}
When I decompile the resulting binary using Reflector, the switch(string) has been changed to ComputeStringHash and then inside each case statement it checks the value via the if statement. Sounds like it's doing double the work.
string s = str2.ToLower();
switch (<PrivateImplementationDetails>.ComputeStringHash(s))
{
case 0x20890fc4:
if (s == "tables")
{
break;
}
goto Label_0218;
case 0x454a414e:
if (s == "functions")
{
goto Label_01DE;
}
goto Label_0218;
case 0x4facf6d1:
if (s == "views")
{
goto Label_01D3;
}
goto Label_0218;
case 0xcdfe2cb3:
if (s == "storedprocs")
{
goto Label_01E9;
}
goto Label_0218;
case 0xd872e2a5:
if (s == "data")
{
goto Label_01F4;
}
goto Label_0218;
case 0x9b4a129b:
if (s == "scripts")
{
goto Label_020C;
}
goto Label_0218;
case 0xba971064:
if (s == "layouts")
{
goto Label_0200;
}
goto Label_0218;
default:
goto Label_0218;
}
first.Add(fullPath);
continue;
Label_01D3:
second.Add(fullPath);
continue;
Label_01DE:
list3.Add(fullPath);
continue;
Label_01E9:
list4.Add(fullPath);
continue;
Label_01F4:
list5.Add(fullPath);
continue;
Label_0200:
list6.Add(fullPath);
continue;
Label_020C:
list7.Add(fullPath);
continue;
Label_0218:
Console.WriteLine("What is this: " + str2);
}
This is a very smart optimization, which lets the switch do its job in time that is almost independent of the number of strings in the case block of the statement.
This optimization is based on the observation that hash codes of identical strings must be the same. Rather than checking strings for equality one-by-one, the compiler computes a hash of the target string once, and performs a table-based lookup in O(1). This gets the compiler to the desired case, at which point the compiler needs to check that the strings are actually equal.
Note that there would be some rare situations when multiple look-up strings would have the same hash code. In such situations the generated case statement would contain multiple if to decide among the strings with equal hash codes.
Overall, this behavior mimics the behavior of hash-based dictionaries: hash code determines the case (an equivalent of a hash bucket) and the series of ifs inside determines if there is a match. This results in a better performance, because it lets the compiler skip the unnecessary checks.

Break tag inside of a method

I have a switch statement that executes some logic over and over. Rather then use cut and paste I wanted to put it into a function, but I am failing badly at this.
This is what I want to do, but it does not compile because the break tag in the function does not exist. Can anyone refactor this to a better working version?
switch(param.ToString())
{
case "1":
BreakIfNotArgumentType<B>(param);
//do stuff
break;
case "2":
BreakIfNotArgumentType<BF>(param);
//do stuff
break;
}
private T BreakIfNotArgumentType<T>(object argumentObject)
{
if (argumentObject is T)
{
return (T)argumentObject;
}
else
{
break;
}
}
Your function is essentially replicating the functionality of the as operator.
string foo = "foo";
....
object a = foo;
object b = 12;
....
string bar = a as string; // will give you "foo"
string zed = b as string; // returns null
The as operator functions as a runtime-safe cast. If the target instance can't be cast to the target type, then a null reference is assigned. Because of this, it will only work with reference types. The most common usage is like this...
string bar = a as string;
if(bar != null)
{
// do stuff
}
Because this gives the type checking and casting operation in one statement.
You should post your switch statement and we may be able to streamline it better. Trying to write a truly inline function as you had (where you were expecting it to substitute the code in the function into your switch statement, which makes it more of a macro than a function) won't work.
You could have the function return a null if the argument can't be cast or throw an exception for a couple of ideas on how to handle that part of the code.
private T BreakIfNotArgumentType<T>(object argumentObject)
{
if (argumentObject is T)
{
return (T)argumentObject;
}
else
{
return null;
}
}
Or
private T BreakIfNotArgumentType<T>(object argumentObject)
{
if (argumentObject is T)
{
return (T)argumentObject;
}
else
{
throw CustomException("Argument wasn't valid!");
}
}
Make your method to return a boolean and check the return value:
switch(param.ToString())
{
case "1":
if (CheckForArgumentType<B>(param))
{
// Do your cast here
param = (B)param
}
else
break;
case "2":
if (CheckForArgumentType<B>(param))
{
// Do your cast here
param = (B)param
}
else
break;
}
.................
private bool CheckForArgumentType<T>(object argumentObject)
{
return (argumentObject is T)
}
if you only have 2 values to compare with - use IF statement instead

Switch over PropertyType

How can I make this work?
switch(property.PropertyType){
case typeof(Boolean):
//doStuff
break;
case typeof(String):
//doOtherStuff
break;
default: break;
}
I don't want to use the name since string comparing for types is just awfull and can be subject to change.
System.Type propertyType = typeof(Boolean);
System.TypeCode typeCode = Type.GetTypeCode(propertyType);
switch (typeCode)
{
case TypeCode.Boolean:
//doStuff
break;
case TypeCode.String:
//doOtherStuff
break;
default: break;
}
You can use an hybrid approach for TypeCode.Object where you dynamic if with typeof. This is very fast because for the first part - the switch - the compiler can decide based on a lookup table.
You can't. What you can do is create a mapping between Types and a delegate using a dictionary:
var TypeMapping = new Dictionary<Type, Action<string>>(){
{typeof(string), (x)=>Console.WriteLine("string")},
{typeof(bool), (x)=>Console.WriteLine("bool")}
};
string s = "my string";
TypeMapping[s.GetType()]("foo");
TypeMapping[true.GetType()]("true");
I think what you are looking for here is a good Map. Using delegates and a Generic IDictionary you can do what you want.
Try something like this:
private delegate object MyDelegate();
private IDictionary<Type, MyDelegate> functionMap = new IDictionary<Type, MyDelegate>();
public Init()
{
functionMap.Add(typeof(String), someFunction);
functionMap.Add(tyepof(Boolean), someOtherFunction);
}
public T doStuff<T>(Type someType)
{
return (T)functionMap[someType]();
}
C# 7.0 will support switch on types as a part of bigger pattern matching feature.
This example is taken from .NET blog post that announces new features:
switch(shape)
{
case Circle c:
WriteLine($"circle with radius {c.Radius}");
break;
case Rectangle s when (s.Length == s.Height):
WriteLine($"{s.Length} x {s.Height} square");
break;
case Rectangle r:
WriteLine($"{r.Length} x {r.Height} rectangle");
break;
default:
WriteLine("<unknown shape>");
break;
case null:
throw new ArgumentNullException(nameof(shape));
}
Do not worry about using strings within a switch because if you have several the compiler will automatically convert it into a hash lookup giving decent performance despite it looking pretty aweful.
The problem of type strings changing can be solved by making it into an explicit hash lookup yourself and populating the constents of the hash in a static constructor. That way the hash is populate with the correct strings at runtime so they remain correct.
You can't do this with switch in c# as the case has to be constant.
What is wrong with:
if(property.PropertyType == typeof(bool)) {
//dostuff;
}
else if (property.PropertyType == typeof(string)) {
//do other stuff;
}
I recently had to do something similar and using switch wasn't an option. Doing an == on the typeof(x) is fine, but a more elegant way might be to do something like this:
if(property.PropertyType is bool){
//dostuff;
}
else if (property.PropertyType is string){
//do other stuff;
}
But, I'm not certain that you can use the "is" keyword in this way, I think it only works for objects...
About the stringmatching: it was one of the reqs in the question to not do it through stringmatching.
The dictionary is an approach I will use when I put this entire serialization algorithm in its own library.
As for now I will first try the typeCode as my case only uses basic types.
If that doesn't work I will go back to the swarm of if/elses :S
Before ppl ask me why I want my own serialization:
1) .net xml serialization doesn't serialize properties without setters
2) serialization has to comply to some legacy rules
Just use the normal if/else if/else pattern:
if (property.PropertyType == typeof(Boolean))
{
}
else if (property.PropertyType == typeof(String))
{
}
else if (...)
{
}
I personally prefer the Dictionary<Type, other> approach the most... I can even provide you another example: http://www.timvw.be/presenting-namevaluecollectionhelper/
In case you insist on writing a switch-case statement you could use the Type name...
switch (blah.PropertyType.FullName)
{
case typeof(int).FullName: break;
case typeof(string).FullName: break;
}

Categories

Resources