Check if value exists. Equals(...) vs. patternMatching - c#

I want to check if a given object value is null or is an empty string. I got the following ideas:
...
public void Cmp1(object a) {
if(a == null || Equals(a, string.Empty)) {
Value = null;
return;
}
....
}
public void Cmp2(object a) {
if(a == null || (a is string stringValue && string.IsNullOrEmpty(stringValue))) {
Value = null;
return;
}
....
}
Which one is better? Is Equals exposing some danger? Or (a is string stringValue && string.IsNullOrEmpty(stringValue)) is super slow?

The problem with the second option is you almost certainly want to use stringValue after the conditional block, meaning you must do the work a second time.
I might use the as operator, like this:
public void Cmp(object a)
{
var stringValue = a as string;
if (string.IsNullOrEmpty(stringValue)) {
Value = null; //this suggests the function should return something, instead of a void method
return;
}
// ...
}
Or I might negate the condition (and remove the null check):
public void Cmp(object a) {
// pattern matching is still safe to use if `a` is null
if(a is string stringValue && !string.IsNullOrEmpty(stringValue)) {
// stringValue is in scope here
}
else {
// but not here... but we no longer need it
Value = null;
}
}
If you don't intend to use stringValue again at all, I'd write it like this:
public void Cmp(object a)
{
if (!(a is string) || string.IsNullOrEmpty((string) a)) {
Value = null;
return;
}
// ...
}
But most of all... none of this is likely to drive the performance of your program. You're spending a bunch of time worrying about details that would be much better spent looking at profiler results, which can tell you exactly where to spend your time optimizing to make your app faster.

Related

Checking number range not working

private bool DataValidation(string Checker)
{
int i;
if (Int32.TryParse(Checker, out i))
{
return true;
}
else
{
return false;
}
}
private void NumberChecker()
{
if (int.Parse(txtRank.Text) >= 0 || int.Parse(txtRank.Text) <= 50)
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
else
{
errorProvider1.SetError(txtRank, "Between 1 and 50 please!");
}
}
private void txtRank_Validating(object sender, CancelEventArgs e)
{
if (DataValidation(txtRank.Text) == false)
{
errorProvider1.SetError(txtRank, "Must be numeric!");
}
else
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
NumberChecker();
}
I've been trying to get this to work for about 4 hours, can someone please tell me why it keeps saying "String in the wrong format" I've tried all of this inside the the validation event, nothing I do is working. I am not understanding why.
Update:
private void txtRank_Validating(object sender, CancelEventArgs e)
{
if (DataValidation(txtRank.Text) == false)
{
errorProvider1.SetError(txtRank, "Must be numeric!");
}
else
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
if (Convert.ToInt32(txtRank.Text) >= 0 && Convert.ToInt32(txtRank.Text) <= 50)
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
else
{
errorProvider1.SetError(txtRank, "Between 1 and 50 please!");
}
}
if i use the code above, i can either do one or the other, but i have to comment out a section of code in order to do that.
You're doing a lot of stuff here that isn't necessary at all.
First off: Assuming that the if statement in your DataValidation method is only intended to have the return true and return false, the if statement is totally unnecessary. You could just say return Int32.TryParse(Checker, out i); and it would do the exact same thing. In fact, you could remove the int i in the first place, and just do this:
private bool DataValidation(string Checker) {
return Int32.TryParse(Checker, out int i);
}
out int i creates a temporary variable... and since the DataValidation method is now a single method call, you may realize that the whole method is now unnecessary. You could simply replace any call to DataValidation(someString) with Int32.TryParse(someString, out int i) with no side effects.
Moving on to your NumberChecker method, the error becomes immediately apparent:
if (int.Parse(txtRank.Text) >= 0 || int.Parse(txtRank.Text) <= 50)
This is the only place in your code where you are parsing a string without checking to ensure that it's a number first. Evidently, txtRank.Text is a string that is not a proper number. This is actually where TryParse would come in handy.
I'm going to assume that you don't know exactly what TryParse does and that you were only using it as an error checker, which is okay, because the function of out arguments aren't immediately apparent.
The out keyword, effectively, allows a function to change the thing that was passed in. Take the following code snippet:
public static void Main(string[] args)
{
String foo = "abc";
DoSomething(out foo);
Console.WriteLine(foo);
}
private static void DoSomething(out String something)
{
something = "def";
}
Despite DoSomething not returning a value, the Console.WriteLine(foo); will write def rather than abc. Int32.TryParse uses this to its advantage: It returns a bool that says whether the operation was successful or not. And if it was successful, it stores the result in the variable used as the out argument.
As such, your NumberChecker method should look something like this:
private void NumberChecker()
{
int num = null;
if (Int32.TryParse(txtRank.Text, out num) {
// if TryParse returns true, then we have a result in `num`.
if (num >= 0 && num <= 50)
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
else // txtRank.Text is a number, but is not within the range
{
errorProvider1.SetError(txtRank, "Between 1 and 50 please!");
}
}
else // txtRank.Text is not a number to begin with
{
errorProvider1.SetError(txtRank, "txtRank.Text is not a number!");
}
}
Worth noting: Since NumberChecker() can now handle the case of invalid text like txtRank_Validating() used to, you can now remove txtRank_Validating() as well. NumberChecker() is now the only necessary code.
One final thing worth noting: In your original code, although your txtRank_Validating() has if statements for in case txtRank.Text was not a number, the reason it was still failing was because NumberChecker() was called at the end of the method whether the text was a number or not. In that sense, the easiest solution would have just been to move the NumberChecker(); call to after errorProvider1.Clear(); inside the else block. But I think the rest of the details in this answer are worth taking note of.

Efficient way to Compare 2 strings for NULL or value and trim to compare if it's not NULL in C#

static void Main(string[] args)
{
string string1 = " "; // it can be NULL and any word too
string string2 = null; // it can be NULL and any word too
if (string.IsNullOrEmpty(string1))
{
if (string.IsNullOrEmpty(string2))
{
Console.WriteLine("Both the string Null & equal");
}
}
else
{
if (!string.IsNullOrEmpty(string2))
{
if(string1.Trim().Equals(string2.Trim(),StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Both the string has value& equal");
}
}
}
}
This code checks for NULL or value of both the string ultimately to confirm both the string is same. Importantly it has to trim the white space to make it comparable and same time if the string is NULL then it can't be trimmed.
Going through all possible conditions, I have written this block of code and still believing someone can make it more efficient in terms of efficiency.
Thank you!
Assuming that you really meant to check for null rather than null or empty (according to your console comment), I'd implement the following method...
private bool checkEqualityWithTrim(string string1, string string2)
{
bool bothNull = string1 == null && string2 == null;
bool bothNonNullAndEqualTrimmed = string1 != null && string2 != null && string1.Trim() == string2.Trim();
return bothNull || bothNonNullAndEqualTrimmed;
}
Then you can just do...
var areEqual = checkEqualityWithTrim(string1, string2);
If the IsNullOrEmpty() was intentional, then just replace the bothNull line with
bool bothNull = string.IsNullOrEmpty(string1) && string.IsNullOrEmpty(string2);
Yeah, you're doing more checks than you need to do. If the strings are equal, you only need to check that one of the strings is null or whitespace. If so, you know the value in both strings. This works assuming that for you NULL and whitespace are equivalent.
public static void Main(string[] args)
{
string string1 = ""; // it can be NULL and any word too
string string2 = ""; // it can be NULL and any word too
if (String.Equals((string1 ?? "").Trim(), (string2 ?? "").Trim(),StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrEmpty(string1)) //since the strings are equal, check one of the strings
{
Console.WriteLine("Both strings are null or empty & equal");
}
else
{
Console.WriteLine("Both strings have values & are equal");
}
}
}
Here is my attempt for you.
If this is something that is going to be used a lot then maybe using extension methods may be the way to go.
I have created two extension methods for you.
1 that performs a null and whitespace check (both conditions will be treated as a null
the second performs the logic you are after.
Here is my attempt for you:
public static bool IsNull(this string source)
{
return string.IsNullOrWhiteSpace(source);
}
public static string IsNullOrSame(this string source, string comparer)
{
//check for both values are null
if (source.IsNull() && comparer.IsNull())
{
return "Both Values Null or contain whitespace only";
}
//check if string 1 is null and string two has a value.
if (source.IsNull() && !comparer.IsNull())
{
return "I don't have a Value, but string 2 does";
}
//check if string 1 has a value and string two is null
if (!source.IsNull() && comparer.IsNull())
{
return "I have Value, but string 2 doesn't";
}
//if we make it this far then both have a value, check if the string value matches
if(source.Trim().Equals(comparer.Trim(), StringComparison.OrdinalIgnoreCase))
{
return "Both value match";
}
//if values don't match
return "strings both have values but don't match";
}
Once you have included these extension methods into your project you can do something simple like:
var string1 = "some value";
var string2 = null;
var result = string1.IsNullOrSame(string2);
Console.WriteLine(result);
this would then result in the message "I have Value, but string 2 doesn't"
The reason for the multiple return statements is one purely for readability. If we meet a "condition" then there is no point performing any more checking and the nesting of multiple if's can get a bit tiresome to debug.
Hopefully this gives you the desired functionality you are after and efficiency.
you are looking for simple and maintainable code not efficiency...
i would code it like that:
(edited: now with all possible conditions)
{
String string1 = "";
String string2 = "";
if (String.IsNullOrEmpty(string1.Trim()) && String.IsNullOrEmpty(string2.Trim()))
{
Console.WriteLine("Both the string Null & equal");
}
else if (!String.IsNullOrEmpty(string1.Trim()) && String.IsNullOrEmpty(string2.Trim()))
{
Console.WriteLine("String2 is null and string1 is not!");
}
else if (String.IsNullOrEmpty(string1.Trim()) && !String.IsNullOrEmpty(string2.Trim()))
{
Console.WriteLine("String1 is null and string2 is not!");
}
else {
if (string1.Trim().Equals( string2.Trim())) {
Console.WriteLine("both strings are not null and Equals!");
}
else {
Console.WriteLine("both strings are not null! and not Equals");
}
}
}
If you can use C# 6 I would definitely suggest you to use the Null Conditional Operator (called also the Elvis operator):
var test = "";
var test2 = "";
if (String.IsNullOrEmpty(test?.Trim()) && String.IsNullOrEmpty(test2?.Trim()))
{
Console.WriteLine("both strings are null or empty and equal");
}
else
{
Console.WriteLine("both strings have value and are equal");
}
Also depending on what the string " " (space) means for you (empty or value) use IsNullOrEmpty (in the case of value) or IsNullOrWhitespace (in the case of empty).

Partial short circuit boolean evaluation in Javascript or C#

Is there a way, in JavaScript or C#, to determine the outcome of a logical expression before the
values of all variables have been retrieved?
Or to put it differently; can an expression be evaluated such that it returns either 'true', 'false', or 'maybe'? Wherein 'maybe' indicates that more data is needed.
To explain: I have a process in which it takes some time to retrieve data from the database backend and I would like to see if we can skip retrieving certain data if not necessary. But the logical expressions have been predetermined and can not be changed or taken apart.
For instance, consider the following expression:
((a = 1) and (b = 2)) or (c = 3)
There are several possibilities:
If a and b have been retrieved but c has not yet been retrieved:
If a=1 and b=2 then the expression will always return true and I can skip retrieving the value for c
If a=0 and b=2 then the first part will be false, and I need to retrieve the value for c in order to being able to determine the outcome
If c has been retrieved, but and a and b have not yet been retrieved.
If c=3 then the expression will always return true and I can skip retrieving the value for a and b.
If c=2 then the first part will be false, and I need to retrieve the value for a and b in order to being able to determine the outcome
In these situations, just knowing that an outcome is already determined, or that more data is needed can significantly speed up a process.
Does anybody have an idea? A process, function, algorithm?
So to cover your very specific code, you can simply use the following:
if(CHasValue())
return (c == 3) or ((a == 1) and (b == 2))
else
return ((a == 1) and (b == 2)) or (c == 3)
short circuiting of operators will take care of the rest.
This doesn't scale very well with more complex expressions though. In order to really cover any arbitrary boolean expression you really need to create your own new type, and corresponding boolean operators.
We'll start out with an interface defining a boolean value that may or may not have computed its value yet:
public interface IComputableBoolean
{
public bool Value { get; }
public bool ValueComputed { get; }
}
The first implementation is the easy one; it's a computable boolean representing a value that we already know:
public class ComputedBoolean : IComputableBoolean
{
public ComputedBoolean(bool value)
{
Value = value;
}
public bool Value { get; private set; }
public bool ValueComputed { get { return true; } }
}
Then there's the slightly more complex case, the boolean value that is generated based on a function (presumably something that is potentially long running, or that has side effects). It will take a delegate that computes the expression, evaluate it the first time the value is requested, and return a cached value (and indicate that it has computed its value) from then on.
public class DeferredBoolean : IComputableBoolean
{
private Func<bool> generator;
private bool? value = null;
public DeferredBoolean(Func<bool> generator)
{
this.generator = generator;
}
public bool Value
{
get
{
if (value != null)
return value.Value;
else
{
value = generator();
return value.Value;
}
}
}
public bool ValueComputed { get { return value != null; } }
}
Now we just need to create And, Or, and Not methods that apply to this interface. They should first check to see if enough values are computed to allow it to short circuit, and if not, they should create a deferred boolean representing the computation of the value. This propagation of deferred values is important, because it allows complex boolean expressions to be composed and still properly short circuit with the minimal amount of needed computation.
public static IComputableBoolean And(
this IComputableBoolean first,
IComputableBoolean second)
{
if (first.ValueComputed && !first.Value ||
second.ValueComputed && !second.Value)
return new ComputedBoolean(false);
else
return new DeferredBoolean(() => first.Value && second.Value);
}
public static IComputableBoolean Or(
this IComputableBoolean first,
IComputableBoolean second)
{
if (first.ValueComputed && first.Value ||
second.ValueComputed && second.Value)
return new ComputedBoolean(true);
else
return new DeferredBoolean(() => first.Value && second.Value);
}
The Not operation is a bit different in that it can't short circuit at all, but it's still important to have in that it continues to defer evaluation of the given boolean expression, because it may end up not being needed.
public static IComputableBoolean Not(
this IComputableBoolean boolean)
{
if (boolean.ValueComputed)
return new ComputedBoolean(boolean.Value);
else
return new DeferredBoolean(() => boolean.Value);
}
We can now represent the expression that you have like so (using actual long running operations to compute a, b, and/or c as needed):
var a = new DeferredBoolean(() => false);
var b = new DeferredBoolean(() => true);
var c = new DeferredBoolean(() => false);
var expression = a.And(b).Or(c);
bool result = expression.Value;
Assuming a, b, c are truthy once they are loaded, and falsy beforehand (or perhaps a,b,c contain a "loaded" property you could check):
var isValid = false;
if (a && b) {
if (a == 1 && b == 2) {
isValid = true;
}
}
if (!isValid && c) {
if (c == 3) {
isValid = true;
}
}

Is there a better way to check for boolean logic

I have an xml filelike so
<Config>
<Allowed></Allowed>
</Config>
The Allowed tag is read like this:
string isAllowed = (string)xml.Root
.Element("Config")
.Elements("Allowed")
.SingleOrDefault();
isAllowed is supposed to take a default value of true when
The tag is not present
Is present but is empty
Has any other value other than true, false, yes, or no.
Here is the code which does this:
if (isAllowed == null)
{
DoSomething();
return true;
}
if (isAllowed.Length == 0)
{
DoSomething();
return true;
}
if (isAllowed.Length != 0)
{
if (isAllowed.ToUpper() != "FALSE" && isAllowed.ToUpper() != "NO")
{
DoSomething();
return true;
}
}
There's got to be a better way to do this?
if (isAllowed == null)
{
DoSomething();
return true;
}
if (isAllowed.Length == 0)
{
DoSomething();
return true;
}
Can be replaced with:
if (string.IsNullOrEmpty(isAllowed)
{
DoSomething();
Return true;
}
But actually, given your criteria I think string.IsNullOrWhiteSpace(isAllowed) would be more appropriate as it will return true if the tag's contents are "empty".
Also, you don't need the following condition a second time, because if if the condition was met the first time around the function will return (short circuit evaluation). This means that the statements you currently have in the second If block would never be executed anyway.
if (isAllowed.Length != 0)
My first instinct to make this cleaner was to take the same approach as Jon did in his answer, there's no advantage in repeating it. However, I did consider this as another good design as should you introduce more conditions it will be much cleaner:
private static bool Validate(string isAllowed)
{
var defaultTrueConditions = new[] {"true", "false", "yes", "no"};
if (string.IsNullOrWhiteSpace(isAllowed) ||
defaultTrueConditions.Contains(isAllowed, StringComparer.OrdinalIgnoreCase))
{
DoSomething();
return true;
}
return false;
}
It sounds like you might be better off like this:
// This deals with the nullity aspect. (The "Yes" is just for clarity - it could
// be any value other than "No" or "False" in some form.)
isAllowed = isAllowed ?? "Yes";
bool isFalse = isAllowed.Equals("No", StringComparison.OrdinalIgnoreCase) ||
isAllowed.Equals("False", StringComparison.OrdinalIgnoreCase);
return !isFalse;
Basically the fact that you're defaulting to true means that the return value should only be false if you find an element and it's got a value of No or False, in a case-insensitive way. Note that I've used an ordinal match here - you may want to change that, e.g. to CurrentCultureIgnoreCase or InvariantCultureIgnoreCase.
It's not clear where the DoSomething method call comes in, but I would separate that out anyway. Write one method which just determines the appropriate value, as shown above - and then have:
bool allowed = CheckAllowed(doc);
if (allowed)
{
DoSomething();
}
// And use allowed here too
That's a much cleaner separation to my mind.

method return types

I'm new to C# and I'm trying to figure out the best way to test if a method returns correctly, ie; did the method get the information I wanted.
It's the types that are making this difficult. Is there a way that I can sometimes return bool and sometimes return something else?
In PHP I would create my function like this
function myFunc(){
//Do Stuff
if(/*whatever*/) return (string) "abcdefg";
return false; //otherwise it will just return false
}
Then call it like this to test if it worked or not
if(!$var=myFunc()) die("It Didn't Work");
echo $var;
But with C#, my function has to return a specified type, not a string or bool false if it didn't work out.
If in C# I have a method that returns IntPtr I could have it return (IntPtr) 0 instead of false, but this is messy and there's probably a better way of doing it.
Any Ideas? What's the standard and usual way of doing this in C#?
There are typically two approaches here:
Use Exceptions
Use the TryXXX approach.
The appropriate method depends on what this is doing. If the "false" case is really something that's exceptional and not the norm, raising an exception is an appropriate way of handling it.
If, however, you're doing something like parsing user input, where its common that you'll "fail", using the TryXXX approach is a good example. This would look like:
bool TryMyFunc(out string result)
{
if (...)
{
result = "abcdefg";
return true;
}
result = string.Empty;
return false;
}
This is how Int32.TryParse works in the framework, for example.
You can always return null.
string Foo()
{
if (!success) return null;
return "abcd";
}
You then check the call like that:
var tmp = Foo();
if (tmp == null) return -1;
// tmp is a string so do your work
The null return will only work with object, unfortunately you can't do that with an int. In that case throw an exception or use a nullable int:
int? Bar()
In your example I would return null from your function in C#:
public string myFunc(){
//Do Stuff
if(/*whatever*/) return "abcdefg";
return null;
}
And then in your calling code:
string myVar = myFunc();
if(null != myVar)
{
throw new Exception();
}
Console.WriteLine(myVar);
It should be noted though that any time you throw exceptions for non-exceptional circumstances (meaning, if your call to myFunc could, in reasonable usage, return null) you will take a serious performance hit. It takes a long time to generate an exception, so it's generally better to avoid them, perhaps by using a pre-requisite check before even calling myFunc.
In circumstances where you're dealing with non-nullable value types, C# has a concept called Nullable Types.
If your Intention is how to return types you can use Tuple<>
public Tuple<string,bool> myFunc()
{
//Do Stuff
if(/*whatever*/) return (string) new Tuple<string,bool>("abcdefg",true);
return new Tuple<string,bool>(null,false);
}
Use Exception based programming:
public string Blah()
{
if (whatever)
{
return "abcdefg";
}
throw new Exception("Something went wrong");
}
Or you could return null or string.Empty
Personally, I prefer use null.
public string foo()
{
if (whatever)
{
return "abc";
}
return null;
}
and Then:
if(foo() != null)
{
//do something
}
else
{
// *It Didn't Work*
}

Categories

Resources