If String.Empty is as good as "", then how come the compiler throws up with string.Empty in the case statement? Nothing can be more constant than string.Empty in my view. Anyone know? Thanks!
switch (filter)
{
case string.Empty: // Compiler error "A constant value is expected"
break;
case "": // It's Okay.
break;
}
You can try like this instead:
switch(filter ?? String.Empty)
string.Empty is a read-only field whereas "" is a compile time constant. You can also go through a article here on Code Project String.Empty Internals
//The Empty constant holds the empty string value.
//We need to call the String constructor so that the compiler doesn't
//mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field
//which we can access from native.
public static readonly String Empty = "";
On a side note:
You will also see this issue when you are providing the default parameter value inside your method(C# 4.0):
void myMethod(string filter = string.Empty){}
The above will result in a compile time error as the default value needs to be a constant.
The reason is: you cannot use readonly values in case: consider the following scenario:
public string MyProperty { get; } // is a read-only property of my class
switch (filter)
{
case MyProperty: // wont compile this since it is read only
break;
// rest of statements in Switch
}
As you said string.Empty is equivalent to "", here I can prove this with the same example of a switch statement:
string filter = string.Empty;
switch (filter)
{
case "": // It's Okay.
break;
//rest of statements in Switch
}
Then the only reason it won't allow string.Empty in case it is read-only, the switch won't allow read-only values in its case.
Related
I have used below code in a project and someone ask me to use ToLower() or ToUpper() and I think it is unnecessary.
public somefun(Classabc clsabc, string emptype, string id)
{
switch(emptype)
{
case :"AnyInput":
{
//do
}
break;
case :"StringInput":
{
//do
}
break;
}
}
if(emptype=="AnyInput")
{
///
}
Is the above perfect or we need to use ToLower() or ToUpper() with empType in if()? Is there any issue or programming rule violation with my code? According to me in case (switch) we are using email type as constant for case matching and if emptype value can be used in case matching then there is no need to add extra functions to convert to there case before string matching.
Depends on what you guys are looking for.
If the comparison is case sensitive, you can keep the switch-case comparison like you did in the example you provided.
In case the comparison is insensitive, you can pattern matching (C# 7 and above) and write something like this:
switch (true)
{
case bool b when emptype.Equals("AnyInput", StringComparison.InvariantCultureIgnoreCase):
// do
break;
case bool b when emptype.Equals("StringInput", StringComparison.InvariantCultureIgnoreCase):
// do
break;
default:
break;
}
Working with a Legacy Application, ASP.Net, c#.
Trying to append my log4net messages with the SessionWrapper.UserDisplayName
The hiccup is if the sessionwrapper is not defined, i don't want it to bomb, i just want it to treat it as null or empty and I'm trying to avoid writing a multiple lines of code.
Using this as the base for my idea:
banana = null;
string result2 = banana?.prop1 + "something new";
result 2 = something new
Applying that concept to my code:
SessionWrapper?.UserDisplayName + "error message"
I get an error compiling saying:
"SessionWrapper is a type and invalid int the current context"
Any insight is greatly appreciated -
A type is not a value and is therefore never null. If UserDisplayName is a static property of this type, then it might be null; however, it is okay to concatenate null with a string. null will be treated like an empty string.
Simply write
string result = SessionWrapper.UserDisplayName + "error message";
In banana?.prop1 the null-condition-operator is only useful if banana is null. The expression is equivalent to banana == null ? (string)null : banana.prop1.
If you want to treat the case where prop1 could be null, then use the null-coalescing operator ??.
string result2 = (banana.prop1 ?? "<empty>") + "something new";
Of course you can combine the two.
string result2 = (banana?.prop1 ?? "<empty>") + "something new";
Now, both, banana and prop1 can be null. In both cases you will get the result "<empty>something new".
In C# 6.0, string interpolations are added.
string myString = $"Value is {someValue}";
How are null values handled in the above example? (if someValue is null)
EDIT:
Just to clarify, I have tested and am aware that it didn't fail, the question was opened to identify whether there are any cases to be aware of, where I'd have to check for nulls before using string interpolation.
That's just the same as string.Format("Value is {0}", someValue) which will check for a null reference and replace it with an empty string. It will however throw an exception if you actually pass null like this string.Format("Value is {0}", null). However in the case of $"Value is {null}" that null is set to an argument first and will not throw.
From TryRoslyn, it's decompiled as;
string arg = null;
string.Format("Value is {0}", arg);
and String.Format will use empty string for null values. In The Format method in brief section;
If the value of the argument is null, the format item is replaced with
String.Empty.
It seems that the behavior depends on which underlying formatting methods are called, and the implementation of these can change over time. If you get a null formated into the string such as "(null)", it is not sure this will stay the same over several years. In some newer version of .NET it can start throwing an exception.
So I think the most safe approach is to make some condition to avoid using the null. Write a simple ternary operation like:
int? someValue = 5;
var valueStr = (someValue is not null) ? someValue.ToString() : string.Empty;
var myString = $"Value is {valueStr}";
It is an extra line of code, but at least the behavior is controlled.
I'm coding a custom query builder from expressions, and at some point I'm saving the value of an expression to my criteria class:
switch(expression.NodeType)
{
case ExpressionType.Constant:
{
//Here there should only be raw values
CriteriaClass newCriteria = new CriteriaClass();
newCriteria.Value = expression; //Value is of 'object' type
return newCriteria;
}
}
And when I'm actually setting up the query, I have a list of all criterias and their values, which seem fine but... their types are all messed up.
The problem is that my next step is converting properly the types of values to the specific DB format:
private string FormatWriteValue(object value, Type type)
{
if (value == null) { return "NULL"; }
if (value.GetType().IsEnum) { return ((int)value).ToString(); }
switch(type.Name)
{
case "Boolean":
case "bool":
return ((bool)value) ? "1" : "0";
case "Int32":
case "int":
return value.ToString();
case "DateTime":
return "CONVERT(DATETIME, '" + ((DateTime)value).ToString("dd/MM/yyyy hh:mm:ss") + "', 103)";
default:
return "'" + value.ToString().Replace("'", "''") + "'";
}
}
Since the type is never one of the basic ones I've typed there, it always falls on the default case for strings.
I've tried casting the value of the expression like this:
criteria.Value = (int)expression; //exception
criteria.Value = Convert.ChangeType(expression, expression.Type); //Type = Int32, but exception again
criteria.Value = Expression.Convert(expression, expression.Type); //Becomes Unary, no exception
I think for the last one to work I'd have to compile the expression, but I've read that it's costly and I'd like to keep this as light as possible.
How can I accomplish this?
When you create your LINQ query to create your data, verify what type of data it is.
So for instance when you do confirm the type, you can parse a string into a DateTime struct like this :Parse string to DateTime in C#
The best thing to do with your LINQ.Expression type is this: Convert it into a string. Then convert that string dynamically into the type you need.
var criteriaToBeConverted = Expression.Call(
Expression.Convert(memberExpression, typeof(object)),
typeof(object).GetMethod("ToString"));
You can learn more about Expression here : http://msdn.microsoft.com/fr-fr/library/system.linq.expressions.expression.call(v=vs.110).aspx
The provided code comes from this actual answer : LINQ Expression Conversion / Concat from Int to string
When you have type as a string, create a method which reads the string and verifies what type the string represents and parse it. Then you return the value as an object.
Hope it helps you out !
If the answer helps you in anyway, check it as answer so others with the same problem can know what to do !
Is it possible to have a switch in C# which checks if the value is null or empty not "" but String.Empty? I know i can do this:
switch (text)
{
case null:
case "":
break;
}
Is there something better, because I don't want to have a large list of IF statements?
I'mm trying to replace:
if (String.IsNullOrEmpty(text))
blah;
else if (text = "hi")
blah
I would suggest something like the following:
switch(text ?? String.Empty)
{
case "":
break;
case "hi":
break;
}
Is that what you are looking for?
What's wrong with your example switch statement?
switch (text)
{
case null:
case "":
foo();
break;
case "hi":
bar();
break;
}
It works (and for some reason that surprised me - I thought it would complain or crash on the null case) and it's clear.
For that matter, why are you worried about String.Empty? I'm missing something here.
how about
if (string.isNullOrEmpty(text))
{
//blah
}
else
{
switch (text)
{
case "hi":
}
}
From the documentation of String.Empty:
The value of this field is the
zero-length string, "".
I interpret this to mean that there is no difference between "" and String.Empty. Why are you trying to distinguish between them?
An empty string is "", which is equal to String.Empty. The reason that you can put "" in a case statement but not "String.Empty" is that "Empty" is a field of the class "String" and "" is actually a contant value.
Constant values are allowed in cases, String.Empty is a field and could be altered at run time. (In this case it will remain the same, but not all static fields of each class are constant values.)
In the case of 'if', that condition is evaluated at run time and if does not require a constant value.
I hope this explains why.
Something that I just noticed is that you can combine if/else and switch statements! Very useful when needing to check preconditions.
if (string.IsNullOrEmpty(text))
{
//blah
}
else switch (text)
{
case "hi":
Console.WriteLine("How about a nice game of chess?");
break;
default:
break;
}
With new c# features, you can use switch expression syntax
text switch
{
"" or null => "a",
_ => "b"
};
string StrMode;
if (!string.IsNullOrEmpty(StrMode))
{
switch (StrMode.Trim())
{
case "Souse":
{
//Statement Eg:
MesssageBox.Show("Souse");
break;
}
case "Company Agent":
{
//Statement Eg:
MesssageBox.Show("Souse");
break;
}
default:
return;
}
}