Related
I am still new to C# and trying to resolve this issue here. I have a method with an int return type, and when I add error message, I get an error and the code doesn't compile.
private static int GetNum(CAP cap)
{
List<Error> errors = new List<Error>();
var unitNumber = cap.pointsAddress["UnitNumbers"];
if (unitNumber == null)
{
// this line of code causes the error
return errors.Add(new Error("Unit not found"));
}
else
{
return int.Parse(unitNumber.AccessAddress);
}
}
Please tell me what I can do to resolve this.
Add returns nothing (i.e. void), it can't be transformed into int. If you want to return some kind of Either type you can return a value tuple:
private static (int? Value, List<Error>? Errors) GetNum(CAP cap)
{
var unitNumber = cap.pointsAddress["UnitNumbers"];
if (unitNumber == null)
{
List<Error> errors = new List<Error>();
errors.Add(new Error("Unit not found"));
return (null, errors);
}
else
{
return (int.Parse(unitNumber.AccessAddress), null);
}
}
And then check the return:
var (val, errors) = GetNum(...);
if(val.HasValue)
{
.... // Use value
}
else
{
// Do something with errors
}
I'd suggest you throw an exception instead of returning an Error.
private static int GetNum(CAP cap)
{
var unitNumber = cap.pointsAddress["UnitNumbers"];
if (unitNumber == null)
{
throw new IndexOutOfRangeException("Unit not found");
}
return int.Parse(unitNumber.AccessAddress);
}
You might additionally, change the function name to GetUnitNumber. Then I'd think about why CAP instances exist with missing values for "UnitNumbers" in the pointsAddress collection.
Your error arises because you specify the return type of your method as int and you are trying to return the return value of the method Add inside the if clause. Adds return type is void, so it does not return anything, which is in conflict to the expected int.
It seems to me that a "TryDoSomeThing" pattern is what you are trying to implement.
In this case you should return a bool to signal whether the procedure has succeeded, and return the real value or the error messages via out.
private static bool TryGetNum(CAP cap, out int num, out List<Error> errors)
{
int num = -1; // choose a default value here
List<Error> errors = new List<Error>();
var unitNumber = cap.pointsAddress["UnitNumbers"];
if (unitNumber == null)
{
errors.Add(new Error("Unit not found")); // add your error messages
return false;
}
else
{
num = int.Parse(unitNumber.AccessAddress); // this will be accessible from the out parameter
return
}
}
Using it similarly like the TryParse methods you could call it like this:
bool result = TryGetNum(cap, out int num, out List<Error> errors);
if(result)
{
// use num here
}
else
{
// use errors here
}
In simple Words a void Method is a Method that does a Action without returning a value, therefore when you ask it for a value such as int it gives you a parsing exception, i'd suggest doing something like this:
private static int GetNum(CAP cap)
{
List<Error> errors = new List<Error>();
var unitNumber = cap.pointsAddress["UnitNumbers"];
if (unitNumber == null)
{
var error = new Error("Unit not found");
errors.Add(error);
//Creating the Error and puting in the list is just writen here right now because i was not sure if you in some way need that to happen, in other words you can remove it if you don't need it
throw new IndexOutOfRangeException("Unit not found");
}
else
{
return int.Parse(unitNumber.AccessAddress);
}
}
The method Add() returns void. When using the output of Add() as the return value for your method, you are trying to output a void value in an int method.
A quick solution for this would be to make the method nullable and then returning a null int, like this:
private static int? GetNum(CAP cap) // Notice the ? after the type, this means it can also be null
{
List<Error> errors = new List<Error>();
var unitNumber = cap.pointsAddress["UnitNumbers"];
if (unitNumber == null)
{
errors.Add(new Error("Unit not found")); // this create the error
return null;
}
else
{
return int.Parse(unitNumber.AccessAddress);
}
}
your expectation :
return error message when there is null/empty
return int
root cause : return type must match method signature declaration.
suggestion : you probably violating Single Responsibilty principal. your method should only do 1 thing, return the value of CAP object. let the caller handle exceptional case.
There are multiple ways to solve your problem, and it is hard to suggest which one is best depends on the usage context.
Throw exception. can treat null, empty as exceptional case. The call will need to catch the method and act accordingly.
return multiple values, which can archive by declare custom type(class or struct) or valueTuples(int,string). which I think is not really fit what you are trying to do.
try pattern. you can refer to it from .net own class library.(eg. Int.TryParse) . the caller need to check for a bool and act accordingly.
change return type from int to int? . caller will need to check for null and display message accordingly.
I have been working on refactoring some code and then i make something like this. Main idea is that i have couple Methods which contains implementations and they change referenced string variable name in my case.
What i don't like here is situation that in every if statement returning same variable (but with different result).
So my question does someone have better idea for eventually refactoring this? Is there any problem doing this in if statements (from logical, clean code side etc).
All my methods have ref keyword (for string variable name). Sorry for confusion!
private string GenerateNameFrom(IRow row)
{
string name = string.Empty;
if (Method1(name,row))
return name;
else if (Method2(name,row))
return name;
else if (Method3(name,row))
return name;
else return "Null";
}
Here is one way to do it:
private string GenerateNameFrom(IRow row)
{
var name = "";
return (Method1(ref name) || Method2(ref name) || Method3(ref name)) ? name : "Null";
}
Using var to instantiate the empty string, no need to write string twice.
Using || means that the first method that returns true will satisfy the condition and no other method will be executed.
Using the ?: operator for conditional return.
Note: As Matthew Watson commented, you are probably missing the ref (or out keyword - because even though a string is a reference type, it's also immutable, so if you want your methods to effect the content of the name argument, you must either send it as ref or as out, since the only way to change it's value is to assign a new string to it.
(also converted the String.Empty to "", but that's just personal preference)
The variable name will always have an empty string. as you declare and initialize just before if statement
Any how below the short way to get the same result. The Result will be same of the below code and your code:
if (Method1(name) || Method2(name) || Method3(name))
{
return name;
}
else
{
return "Null";
}
Or more specifically using ternary operator
(Method1(name) || Method2(name) || Method3(name)) ? name : "Null";
Can't see the implementation of your methods but I'm assuming something like:
public bool Method1(ref string name)
{
if (condition)
{
name = "SomeValue";
return true;
}
return false;
}
You could refactor those methods to return the updated name:
public string Method1(name)
{
if(condition)
{
return "SomeValue";
}
return null;
}
And then you could just null coalesce the method calls:
private string GenerateNameFrom(IRow row)
{
string name = string.Empty;
return Method1(name)
?? Method2(name)
?? Method3(name)
?? "Null";
}
Well all of this Method1(name) and Method2(name) doing some validation over the input string name and returning bool. In that case would suggest you to combine all those validation logic inside single method using a switch statement probably and use that method instead
I would try to avoid using ref in this case. Instead, you could make the various methods return a tuple (bool success, string value) like so:
public static (bool success, string value) Method1(string name)
{
if (name == "test")
return (true, "changed");
return (false, null);
}
public static (bool success, string value) Method2(string name)
{
if (name == "test")
return (true, "changed");
return (false, null);
}
public static (bool success, string value) Method3(string name)
{
if (name == "test")
return (true, "changed");
return (false, null);
}
Then you can write the calling code like so (it's not shorter, but it avoids ref). Whether you like this better is probably a matter of taste...
private string GenerateNameFrom(/*IRow row*/)
{
string name = string.Empty;
var result = Method1(name);
if (result.success)
return result.value;
result = Method2(name);
if (result.success)
return result.value;
result = Method3(name);
if (result.success)
return result.value;
return null;
}
Alternatively, if null can be used to indicate "no result" then just do a similar thing but checking the return value for null:
private string GenerateNameFrom(/*IRow row*/)
{
string name = string.Empty;
var result = Method1(name);
if (result != null)
return result;
result = Method2(name);
if (result != null)
return result;
return Method3(name);
}
public static string Method1(string name)
{
if (name == "test")
return "changed";
return null;
}
public static string Method2(string name)
{
if (name == "test")
return "changed";
return null;
}
public static string Method3(string name)
{
if (name == "test")
return "changed";
return null;
}
I have a field in a database (whose schema I can't change) which contains a specific set of values. Let's call them H, M, and L. H stands for High, M for Medium, and L is for Low. In C# I'd like to be able to reference these values in a typesafe way, but one that is also readable in code.
Currently there's a lot of this pattern littering the repository:
public static class Priority
{
public const string High = "H";
public const string Medium = "M";
public const string Low = "L";
}
Which does provide the readability but isn't typesafe and could potentially be dangerous if lowercase values make their way into the database (unlikely but not impossible).
Is there a better way to handle this pattern?
You can implement this as a combination of an enum and a static class encapsulating logic for it, like this:
public enum Priority { High, Medium, Low }
public static class Priorities {
public static string GetCode(this Priority priority) {
switch (priority) {
case Priority.High: return "H";
case Priority.Medium: return "M";
case Priority.Low: return "L";
}
throw new ArgumentException("priority");
}
public static Priority GetPriority(string priorityCode) {
switch (priorityCode) {
case "H": return Priority.High;
case "M": return Priority.Medium;
case "L": return Priority.Low;
}
throw new ArgumentException("priorityCode");
}
}
Now you can use Priorities.GetPriority(codeFromDatabase) to make an element of Priority enumeration from a DB code, and call
priority.GetCode()
to obtain a code for writing a Priority back to the database.
There are two ways I'd deal with this, depending on the situation.
The first is to use an enum and a Dictionary<TKey, TValue> to map a character to an entry in the enum.
enum Priority : byte
{
High,
Medium,
Low
}
static class Priorities
{
private static Dictionary<char, Priority> _toPriority = new Dictionary<char, Priority>();
private static Dictionary<Priority, char> _fromPriority = new Dictionary<Priority, char>();
static Priorities()
{
var priorities = Enum.GetNames(typeof(Priority));
var values = (Priority[])Enum.GetValues(typeof(Priority));
for (var i = 0; i < priorities.Length; i++)
{
_toPriority.Add(priorities[i][0], values[i]);
_fromPriority.Add(values[i], priorities[i][0]);
}
}
public static Priority GetPriority(string field)
{
Priority res;
if (!TryGetPriority(field, out res))
throw new ArgumentException("Invalid priority on field.", "field");
return res;
}
public static bool TryGetPriority(string field, out Priority priority)
{
if (field == null || field.Length == 0) { priority = default(Priority); return false; }
return _toPriority.TryGetValue(field[0], out priority);
}
public static char GetCode(Priority priority)
{
return _fromPriority[priority];
}
}
Another way to do this would be to create a struct which creates itself in public static readonly fields.
struct Priority
{
public static readonly Priority High = new Priority('H');
public static readonly Priority Medium = new Priority('M');
public static readonly Priority Low = new Priority('L');
static Priority()
{
register(High);
register(Medium);
register(Low);
}
public static bool TryGetPriority(char code, out Priority priority)
{
return _map.TryGetValue(code, out priority);
}
public static Priority GetPriority(char code)
{
Priority priority;
if (!TryGetPriority(code, out priority))
throw new ArgumentException("Code doesn't represent an existing priority.", "code");
return priority;
}
public override int GetHashCode()
{
return _code.GetHashCode();
}
public override bool Equals(object obj)
{
if (!(obj is Priority)) return false;
return ((Priority)obj)._code == _code;
}
public override string ToString()
{
return _code.ToString();
}
public static implicit operator char(Priority #this) { return #this._code; }
public static explicit operator Priority(char code)
{
Priority result;
if (!_map.TryGetValue(code, out result))
throw new InvalidCastException();
return result;
}
private static readonly Dictionary<char, Priority> _map = new Dictionary<char, Priority>();
private static void register(Priority p)
{
_map.Add(char.ToLowerInvariant(p._code), p);
_map.Add(char.ToUpperInvariant(p._code), p);
}
private readonly char _code;
private Priority(char code) { _code = code; }
}
Method 1:
Pros: You only have to define the enum the result will automatically update. You can access both the full name (enumInstance.ToString()) and the code.
Cons: You need to explicitly call conversion methods to change between the char and Priority.
Method 2:
Pros: The type will implicitly convert to char, and can be cast from char.
Cons: You have to update both the calls to register and the enum to add or modify entries. You cannot access the full name of the field.
Both cons on method two can be resolved easily. The first can be resolved by using reflection to discover all public fields. The second by either adding it as parameter to the constructor or also through reflection.
Using method 1:
Priority p = Priority.High; // Assign literal
MessageBox.Show(p.ToString()); // High
MessageBox.Show(Priorities.GetCode(p).ToString()); // H
Priority p = Priorities.GetPriority('L'); // Cast from character
MessageBox.Show(p.ToString()); // Low
MessageBox.Show(Priorities.GetCode(p).ToString()); // L
Priority p; // Safe assigning
if (!Priorities.TryGetPriority('M', out p))
return;
MessageBox.Show(p.ToString()); // Medium
MessageBox.Show(Priorities.GetCode(p).ToString()); // M
Using method 2:
Priority p = Priority.High; // Assign literal
MessageBox.Show(p.ToString()); // H
Priority p = (Priority)'L'; // Cast from character
MessageBox.Show(p.ToString()); // L
Priority p; // Safe assigning
if (!Priority.TryGetPriority('M', out p))
return; // Handle invalid scenario
MessageBox.Show(p.ToString()); // M
Personally I think this solution is much cleaner than relying on two switches and the definition. Performance wise (it won't really matter unless you have an incredibly large database) it'll perform very similar to the switch statement. A switch statement in the right condition will be compiled an in-code hashmap, just like a Dictionary<TKey, TValue> is a hashmap.
If you want to have multi-character strings just change char to string.
I'm trying to write a validation method. Eg: for double it looks like this:
protected bool ValidateLoopAttributes(string i_value, double i_threshold)
{
double result;
if (!(double.TryParse(i_value, out result) && result >= i_threshold))
{
return false;
}
return true;
}
Is it possible to write this as:
protected bool ValidateLoopAttributes<T>(string i_value, T i_threshold)
and then use something like
T.GetType().TryParse() // how can i use here the type's methods??
Is using a switch/if statement the only way to do this? Eg:
If (T.GetType() is int)
Int32.TryParse(i_threshold)
Is there a more elegant way?
Try this:
static class Ext
{
public static bool TryParse<T>(string s, out T value)
{
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
try
{
value = (T)converter.ConvertFromString(s);
return true;
}
catch
{
value = default(T);
return false;
}
}
public static bool ValidateLoopAttributes<T>(string i_value, T i_threshold)
where T : IComparable
{
T outval;
if (TryParse<T>(i_value, out outval))
return outval.CompareTo(i_threshold) >= 0;
else return false;
}
}
My answer uses Marc Gravell's answer taken from here.
With this you can do
bool b1 = Ext.ValidateLoopAttributes<int>("5", 4);
bool b2 = Ext.ValidateLoopAttributes<double>("5.4", 5.5d);
If you find it useful you can also use an extension method
public static bool ValidateLoopAttributes<T>(this string i_value, T i_threshold)
where T : IComparable { }
which leads you to use
bool b1 = "5".ValidateLoopAttributes<int>(4);
bool b2 = "5.4".ValidateLoopAttributes<double>(5.5d);
Currently you are mixing two things inside your method - parsing and business rules. Consider you invoke ValidateLoopAttributes(value, 4) and it returns false. Possible reasons:
String does not contain value. E.g. empty, some characters, etc.
String does not contain integer value. E.g. it has double value.
String contains integer value, but it exceeds threshold.
No converters defined for your type.
In first case you have invalid data in your source.
In second case you have invalid code, which should use double instead.
In third case code is OK, but business rule was broken.
In last case (which is not case for doubles or integers, but if you write generic code with no restrictions on type, you allow others to call it with any type) also problem in code.
So, think about separating business rules and parsing data.
Foo foo = Parse(xml);
RunBusinessRules(foo);
public static bool ValidateLoopAttributes<T>(string value, T threshold)
where T : IComparable
{
try
{
var parseMethod = typeof(T).GetMethod("Parse", new[] {typeof (string)});
var result = (T) parseMethod.Invoke(null, new object[] {value});
return result.CompareTo(threshold) < 0;
}
catch (Exception)
{
return false;
}
}
Obviously, this only works for types with a static Parse method.
Can try to use something like this to check if this is an integer or not:
public static bool IsNumericValue(string val, System.Globalization.NumberStyles NumberStyle)
{
double result;
return Double.TryParse(val,NumberStyle,
System.Globalization.CultureInfo.CurrentCulture,out result);
}
so on
IsNumericValue("1.2", System.Globalization.NumberStyles.Integer) // FALSE
and on
IsNumericValue("12", System.Globalization.NumberStyles.Integer) // TRUE
Pay attention that in this example I used CurrectCulture, fit it to your needs, if they are different.
I continuously check string fields to check if they are null or blank.
if(myString == null || myString.Trim().Length == 0)
{
throw new ArgumentException("Blank strings cannot be handled.");
}
To save myself a bit of typing is it possible to create an extension method for the String class that would have the same effect? I understand how extension methods can be added for a class instance but what about adding a static extension method to a class?
if(String.IsNullOrBlank(myString))
{
throw new ArgumentException("Blank strings cannot be handled.");
}
You could do:
public static bool IsNullOrBlank(this String text)
{
return text==null || text.Trim().Length==0;
}
And then call it like this:
if(myString.IsNullOrBlank())
{
throw new ArgumentException("Blank strings cannot be handled.");
}
This works because C# allows you to call extension method on null instances.
I know this is an old question but since it was bumped and it hasn't been mentioned already, as of .NET 4.0 you can simply use the String.IsNullOrWhiteSpace method to achieve the same result.
You can safely use an extension method on the instance:
public static class StringExtensions
{
public static bool IsNullOrBlank(this string s)
{
return s == null || s.Trim().Length == 0;
}
}
Test cases:
string s = null;
Assert.IsTrue(s.IsNullOrBlank());
s = " ";
Assert.IsTrue(s.IsNullOrBlank());
It looks a bit weird though, and I would instead figure out why your strings need to be checked for this case so often. If you fix them at the source, you won't have to be so paranoid about them later!
Can you add static methods to existing classes? The answer is no, and the value would be pretty thin, because you'd still need to know which class name to type first; with extension methods, the advantage is that you start with a variable name and autocompletion shows you things that are applicable to it.
Another point often made is that extension methods should always throw an exception as soon as possible if their first argument is null. However, I think that rule is overkill if the method mentions in its name that it is designed to check for null.
The real problem you have is that you want to neatly and readably run some code after checking for a null reference. One way to capture that pattern is in my answer to this question.
An overload to the existing answers could be:
public static bool IsNullOrBlank(this String text, Action<String> doWhat)
{
if (text!=null && text.Trim().Length>0)
doWhat(text);
}
Would be helpful if you only want to run code given a valid value.
Not a super useful example, but just showing the usage:
Name.IsNullOrBlank(name=>Console.WriteLine(name));
A bit late. But you can also put the code to throw an exception in an extension method too. I have two methods (for ArgumentNullException and NullReferenceException).
// strings
public static bool NullBlankCheck(this string s, string message = "",
bool throwEx = true)
{
return Check<NullReferenceException>(s.IsNullOrBlank(), throwEx, message);
}
public static bool NullBlankCheckArgument(this string s, string message = "",
bool throwEx = true)
{
return Check<ArgumentException>(s.IsNullOrBlank(), throwEx, message);
}
private static bool Check<T>(bool isNull, bool throwEx, string exceptionMessage)
where T : Exception
{
if (throwEx && isNull)
throw Activator.CreateInstance(typeof(T), exceptionMessage) as Exception;
return isNull;
}
public static bool IsNullOrBlank(this string s)
{
return string.IsNullOrEmpty(s) || s.Trim().Length == 0;
}
nunit tests:
Assert.Throws<NullReferenceException>(() =>
{
"".NullEmptyCheck();
});
Assert.Throws<ArgumentException>(() =>
{
"".NullEmptyCheckArgument();
});
And then use it as:
public void Method(string someStr)
{
someStr.NullBlankCheckArgument();
// do something
var str = someMethod();
str.NullBlankCheck();
}
public static bool IsNullOrEmptyTrimmed(string value)
{
return (value == null || value.Length == 0) ?
true : value.Trim().Length == 0;
}
or
public static bool IsNullOrEmpty(this String value, bool checkTrimmed)
{
var b = String.IsNullOrEmpty(value);
return checkTrimmed ? (b && value.Trim().Length > 0) : b;
}
Although, this question was asked over a decade ago, I see no one has mentioned that there is a built in string method for handling this.
Therefore, please use string.IsNullOrWhitespace() instead. No hacking anything in, use the language feature and you're just fine.
With a few tricks, you make it look like you've added to the String class in any one cs file:
namespace JDanielSmith
{
public static class String
{
public static bool IsNullOrBlank(string text)
{
return text == null || text.Trim().Length == 0;
}
}
}
(note, this is not an extension method, see my comment).
Then, in some other CS file:
using String = JDanielSmith.String;
namespace Foo.Bar.Baz
{
class Program
{
static void test(string myString)
{
if (String.IsNullOrBlank(myString))
{
throw new ArgumentException("Blank strings cannot be handled.");
}
}
...
Notice the "desired" syntax of String.IsNullOrBlank(). I'm not necessarily suggesting that you actually do things this way, just pointing out how you could set things up to make your code work.
public static bool IsNull(this object o)
{
return string.IsNullOrEmpty(o.ToStr());
}
public static bool IsNotNull(this object o)
{
return !string.IsNullOrEmpty(o.ToStr());
}
public static string ToStr(this object o)
{
return o + "";
}