I have a VB.Net function that is useful for checking if a database record is null or not, and replace it with a default value if it is.
Public Function NZ(input As Object, Optional ifNull As Object = "") As Object
If IsDBNull(input) Or input Is Nothing Then
Return ifNull
Else
Return input
End If
End Function
I'm trying to get the same functionality in C#, but it doesn't like using objects the same way.
The closest I've gotten is
public static object NZ(object input, object ifNull)
{
if(input == DBNull.Value || input == null)
{
return ifNull;
}
else
{
return input;
}
}
but I get several errors with "cannot convert object to string" and the like.
I have tried to make a more specific version
public static string NZ(string input, string ifNull)
{
if (input == DBNull.Value || input == null)
{
return ifNull;
}
else
{
return input;
}
}
but that gives a "Operator '==' cannot be applied to operands of type string and DBNull"
I'm hoping there is an easy way to do this.
Use Convert.IsDbNull
The code will be something like this:
public static string NZ(object input, string ifNull)
{
return Convert.IsDbNull(input) ? ifNull : input;
}
If you want it to be more concise, write an extension method:
public static class DbNullExt
{
public static string ValueOrDefault(this object input, string ifNull)
=> Convert.IsDbNull(input) ? ifNull : input?.ToString();
public static string ValueOrDefaultIfDbNullOrNull(this object input, string ifNull)
=> Convert.IsDbNull(input) ? ifNull : input?.ToString() ?? ifNull;
}
And then simply invoke it as
var valueOrDefault = input.ValueOrDefault("ifItIsDbNull");
Use Information.IsDBNull
public object NZ(object input, object ifNull)
{
if (Information.IsDBNull(input) || input == null)
return ifNull;
else
return input;
}
Related
I have Web API which throws an error if one of the parameters passed in a URL query is null. Let's say I cant overwrite anything to the above validation.
So that, I want to have a Web API as below, the parameter c is string and the API call may pass an empty string which instantiates parameter c as null and not "".
[Route("{id}")]
[HttpGet]
public IdDTO GetIdDetails(
int Id,
[FromUri] int a,
[FromUri] string b,
[FromUri] string c,
{
//doing something here...
}
A typical API call is localhost:3000/123?a=1&b=abc&c=
I also changed the data type of c to a custom datatype ReqString ([FromUri] ReqString <string> c) as below
public struct ReqString<T>
{
private T _value;
public ReqString(T s)
{
_value = s;
}
public static implicit operator ReqString<T>(T s) => new ReqString<T>(s);
public static implicit operator string(ReqString<T> s)
{
if(typeof(T).Equals(typeof(string)))
{
return s._value as string == null ? "" : s._value as string;
}
else
{
return s._value.ToString();
}
}
}
The problem now is, the value for c is "". But if I pass values for parameter c in API URL query, it is still "" and not the value passed
for eg: localhost:3000/123?a=1&b=abc&c=def
ie, the _value is still null
So my question is How can I use implicit operators to instantiate _value with query value?
UPDATE
The custom datatype works when instantiated in a statement as below, but I want to get similar result in a function call parameter
ReqString rStr = "testing";
As per Michael comment, I took a look into ModalBinder. I was able to resolve my issue. Below is the sample solution I used
public class ReqStringModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(ReqString))
{
return false;
}
ValueProviderResult val = bindingContext.ValueProvider.GetValue(
bindingContext.ModelName);
if (val == null)
{
return false;
}
string key = val.RawValue as string;
if (key == null)
{
bindingContext.ModelState.AddModelError(
bindingContext.ModelName, "Wrong value type");
return false;
}
ReqString result;
if (ReqString.TryParse(key, out result))
{
bindingContext.Model = result;
return true;
}
bindingContext.ModelState.AddModelError(
bindingContext.ModelName, "Cannot convert value to ReqString");
return false;
}
}
[ModelBinder(typeof(ReqStringModelBinder))]
public class ReqString
{
public string value { get; set; }
public static bool TryParse(string s, out ReqString result)
{
result = null;
result = new ReqString() { value = String.IsNullOrEmpty(s) ? "" : s };
return true;
}
public static implicit operator string(ReqString reqString) => reqString.value;
}
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 am trying t get this working but somehow its going out of my hand... I want to be able to check null or empty to whatever type i assigned.
EX:
int i =0;
string mystring = "";
var reult = CheckNullOrEmpty(10) // passing int
var result 1 = CheckNullOrEmpty(mystring) // passing string
public bool CheckNullOrEmpty<T>(T value)
{
// check for null or empty for strings
// check for null i.e. 0 for int
}
can someone help me with this.. I am trying to understand how generics works for this simple method.
public static bool CheckNullOrEmpty<T>(T value)
{
if (typeof(T) == typeof(string))
return string.IsNullOrEmpty(value as string);
return value == null || value.Equals(default(T));
}
How to use:
class Stub { }
bool f1 = CheckNullOrEmpty(""); //true
bool f2 = CheckNullOrEmpty<string>(null); //true
bool f3 = CheckNullOrEmpty(0); //true
bool f4 = CheckNullOrEmpty<Stub>(null); //true
You can check against default(T);
public bool CheckNullOrEmpty<T>(T value)
{
return value == default(T);
}
For more informations: http://msdn.microsoft.com/en-us/library/xwth0h0d.aspx
You can use default() -
e.g.:
if(value != default(T))
from MSDN:
Given a variable t of a parameterized type T, the statement t = null
is only valid if T is a reference type and t = 0 will only work for
numeric value types but not for structs. The solution is to use the
default keyword, which will return null for reference types and zero
for numeric value types. For structs, it will return each member of
the struct initialized to zero or null depending on whether they are
value or reference types.
http://msdn.microsoft.com/en-us/library/xwth0h0d(v=vs.80).aspx
Because your CheckNullOrEmpty implementation differs by type, you can't have that check as a generic function.
If you use Nullable value types however, you can use GetValueOrDefault():
int? i = 0;
var result = i.GetValueOrDefault(10);
Then for string, just have an extension method:
public static string GetValueOrDefault(this string item, string defaultValue = "")
{
return !string.IsNullOrWhiteSpace(item) ? item : defaultValue;
}
Then you can do:
string i = null;
string mystring = "";
var result = i.GetValueOrDefault(mystring);
I've added a couple of re-factorings:
1. DBNull is not seen as isnullorempty so added the (value as string)
2. Passing a datatable row[column] that was created dynamically at runtime (like: row["PropertyName"]) will not see this as a string with typeof(T) due to the fact that the column type base is object. So added an extra check for typeof(object) and if not null test that the ToString() is empty value. I haven't tested this fully so may not work for all types of data columns.
public static bool CheckNullOrEmpty<T>(T value)
{
// note: this does not see DBNull as isnullorempty.
if (typeof(T) == typeof(string))
{
if (!string.IsNullOrEmpty(value as string))
{
return string.IsNullOrEmpty(value.ToString().Trim());
}
else
{
return true;
}
}
else if (typeof(T) == typeof(object))
{
// note: datatable columns are always seen as object at runtime with generic T regardless of how they are dynamically typed?
if (value != null) {
return string.IsNullOrEmpty(value.ToString().Trim());
}
}
return value == null || value.Equals(default(T));
}
I'm trying to run the following code but get a casting error.
How can I rewrite my code to achive the same ?
boolResult= (bool?)dataReader["BOOL_FLAG"] ?? true;
intResult= (int?)dataReader["INT_VALUE"] ?? 0;
Thanks
Use the "IsDbNull" method on the data reader... for example:
bool? result = dataReader.IsDbNull(dataReader["Bool_Flag"]) ? null : (bool)dataReader["Bool_Flag"]
Edit
You'd need to do something akin to:
bool? nullBoolean = null;
you'd have
bool? result = dataReader.IsDbNull(dataReader["Bool_Flag"]) ? nullBoolean : (bool)dataReader["Bool_Flag"]
Consider doing it in a function.
Here's something I used in the past (you can make this an extension method in .net 4):
public static T GetValueOrDefault<T>(SqlDataReader dataReader, System.Enum columnIndex)
{
int index = Convert.ToInt32(columnIndex);
return !dataReader.IsDBNull(index) ? (T)dataReader.GetValue(index) : default(T);
}
Edit
As an extension (not tested, but you get the idea), and using column names instead of index:
public static T GetValueOrDefault<T>(this SqlDataReader dataReader, string columnName)
{
return !dataReader.IsDBNull(dataReader[columnName]) ? (T)dataReader.GetValue(dataReader[columnName]) : default(T);
}
usage:
bool? flag = dataReader.GetValueOrDefault("BOOL_COLUMN");
There's an answer here that might be helpful:
https://stackoverflow.com/a/3308515/1255900
You can use the "as" keyword. Note the caution mentioned in the comments.
nullableBoolResult = dataReader["BOOL_FLAG"] as bool?;
Or, if you are not using nullables, as in your original post:
boolResult = (dataReader["BOOL_FLAG"] as bool?) ?? 0;
bool? boolResult = null;
int? intResult = null;
if (dataReader.IsDBNull(reader.GetOrdinal("BOOL_FLAG")) == false)
{
boolResult = dataReader.GetBoolean(reader.GetOrdinal("BOOL_FLAG"));
}
else
{
boolResult = true;
}
if (dataReader.IsDBNull(reader.GetOrdinal("INT_VALUE")) == false)
{
intResult= dataReader.GetInt32(reader.GetOrdinal("INT_VALUE"));
}
else
{
intResult = 0;
}
I'm sure I found the inspiration for this somewhere around the interweb but I can't seem to find the original source anymore. Anyway, below you find a utility class which allows to define an extension method on DataReader, like this:
public static class DataReaderExtensions
{
public static TResult Get<TResult>(this IDataReader reader, string name)
{
return reader.Get<TResult>(reader.GetOrdinal(name));
}
public static TResult Get<TResult>(this IDataReader reader, int c)
{
return ConvertTo<TResult>.From(reader[c]);
}
}
Usage:
reader.Get<bool?>("columnname")
or
reader.Get<int?>(5)
Here's the enabling utility class:
public static class ConvertTo<T>
{
// 'Factory method delegate', set in the static constructor
public static readonly Func<object, T> From;
static ConvertTo()
{
From = Create(typeof(T));
}
private static Func<object, T> Create(Type type)
{
if (!type.IsValueType) { return ConvertRefType; }
if (type.IsNullableType())
{
return (Func<object, T>)Delegate.CreateDelegate(typeof(Func<object, T>), typeof(ConvertTo<T>).GetMethod("ConvertNullableValueType", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(new[] { type.GetGenericArguments()[0] }));
}
return ConvertValueType;
}
// ReSharper disable UnusedMember.Local
// (used via reflection!)
private static TElem? ConvertNullableValueType<TElem>(object value) where TElem : struct
{
if (DBNull.Value == value) { return null; }
return (TElem)value;
}
// ReSharper restore UnusedMember.Local
private static T ConvertRefType(object value)
{
if (DBNull.Value != value) { return (T)value; }
return default(T);
}
private static T ConvertValueType(object value)
{
if (DBNull.Value == value)
{
throw new NullReferenceException("Value is DbNull");
}
return (T)value;
}
}
EDIT: makes use of the IsNullableType() extension method defined like so:
public static bool IsNullableType(this Type type)
{
return
(type.IsGenericType && !type.IsGenericTypeDefinition) &&
(typeof (Nullable<>) == type.GetGenericTypeDefinition());
}
Here's my shot at an extension method. Column name semantics and falls back to default(T) when a null is encountered.
public static class DbExtensions
{
public static T ReadAs<T>(this IDataReader reader, string col)
{
object val = reader[col];
if (val is DBNull)
{
// Use the default if the column is null
return default(T);
}
return (T)val;
}
}
Here is the sample usage. Remember that despite string being a reference type, it will still fail to cast to null from a DBNull. The same is true with int?.
public Facility Bind(IDataReader reader)
{
var x = new Facility();
x.ID = reader.ReadAs<Guid>("ID");
x.Name = reader.ReadAs<string>("Name");
x.Capacity = reader.ReadAs<int?>("Capacity");
x.Description = reader.ReadAs<string>("Description");
x.Address = reader.ReadAs<string>("Address");
return x;
}
using extension method:
public static T GetValueOrDefault <T> (this SqlDataReader reader, string column) {
var isDbNull = reader[column] == DBNull.Value;
return !isDbNull ? (T) reader[column] : default (T);
}
Remember that a DBNull is not the same thing as null, so you cannot cast from one to the other. As the other poster said, you can check for DBNull using the IsDBNull() method.
Try this version. It performs some basic conversion and manages default values as well.
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 + "";
}