Is this the best approach using generics to check for nulls? - c#

public static T IsNull<T>(object value, T defaultValue)
{
return ((Object.Equals(value,null)) | (Object.Equals(value,DBNull.Value)) ?
defaultValue : (T)value);
}
public static T IsNull<T>(object value) where T :new()
{
T defaultvalue = new T();
return IsNull(value, defaultvalue);
}
Have tested, and can use against data objects, classes and variables.
Just want to know if there is better way to go about this.

It looks like you're trying to duplicate the null coalesce operator:
var foo = myPossiblyNullValue ?? defaultValue;

First off, the method name is wrong. You imply that the result of the function is a boolean that is true exactly if the given value is null. In fact, that’s not the case. GetValueOrDefault might be a better name.
Secondly, you’re merely replicating the behaviour of the null coalesce operator, as mentioned by others.
Thirdly, your conditional is odd:
Object.Equals(value,null)) | (Object.Equals(value,DBNull.Value)
Why Object.Equals instead of ==? Better yet, use Object.ReferenceEquals since that makes it clear that you’re interested in reference equality. Also, you’re using the bitwise-or operator (|) which is semantically wrong in this context, although it happens to yield the right value. You want the boolean-or operator ||. (Also, inconsistency: why do you sometimes write object and other times Object?)
Finally, using type object instead of a generic type isn’t necessarily a good solution. It would be better to create overloads for generic reference and value types: this avoids boxing in the value types. It also means that you don’t have to specify the type explicitly in your second overload since it can be deduced from the method argument.

public static bool IsNull<T>(object value)
{
return object == default(T);
}

[Edited]
The following (non-generic) should work.
public static bool IsNull(object value)
{
return value == null;
}
Any value type will get boxed (i.e. non-null). Ref types will just be passed by pointer.

Related

default(T?) does not return null when T is a value type

I've come across the following phenomenon and am absolutely bamboozled. I'm using C# 10 with nullables enabled.
default(int?) returns null as expected. The following function, however, returns whatever default(T) is
public static T? ShouldReturnNull<T>()
{
return default(T?);
}
In the case of ShouldReturnNull<int>() we get 0. Shouldn't it also return null?
I have the following code in my program where this becomes an issue:
public T?[] FindKElements(...)
{
var result = new (T, double)?[k];
// ... populate result array,
// possibly including null values...
// return an array containing only the T part or null
return result.Select(e => e is null ? default(T?) : e.Value.Item1).ToArray();
}
Is there a way to keep it this generic but with proper nulls instead when T is a value type? The compiler won't let me use null in place of default(T?).
In the absence of a where T : struct constraint, T? does not mean Nullable<T>; it means "T, but note that it won't be null in the NRT sense" - and since NRT nulls never apply to your value-type scenario: it basically just means T; and the default value of a value-type T is not null (in any sense).
In the scenario where you need "null checking" that crosses both value-type and reference-type scenarios including support for value-types without a value, then the easiest approach is usually to forget about Nullable<T> and just track:
do I have a value (bool), and
what is the value (T)
separately, and explicitly; this could be via any of:
bool SomeMethod(out var T)
(HasValue: bool, Value: T) SomeMethod()
Maybe<T> SomeMethod()
(where Maybe<T> is just a custom struct that is composed of a bool HasValue and a T Value)
This is effectively creating something akin to Nullable<T>, but which applies to all values, regardless of type. Instead of checking for null, just check .HasValue first, and if true, assume that the value is meaningful.

Aggregate: Seed with a null value [duplicate]

private static Matcher<T> EqualTo<T>(T item)
{
return new IsEqual<T>(item);
}
How do I modify the above method definition such that the following are valid/allowed.
EqualTo("abc");
EqualTo(4);
EqualTo(null); // doesn't compile. EqualTo<string>(null) does
Trying to port some Java code where null seems to be acceptable value for a T parameter.
Update
Thanks: for all the answers - especially Eamon and Jason. I didn't want the method calls to bother with type-inference. The following overload fixed it.
private static Matcher<object> EqualTo(object item)
{
return EqualTo<object>(item);
}
Actually the above question was a part of a larger puzzle. The end goal was for the following to work.
this.AssertThat(null, EqualTo(null));
this.AssertThat(null, Not(EqualTo("hi")));
this.AssertThat("hi", Not(EqualTo(null)));
Applied the same fix.. RFC. (Ignore the ugly extension method part - that's another problem. Wanted to have these methods in all test-fixtures without inheritance.)
public static void AssertThat<T>(this object testFixture, object actual, Matcher<T> matcher, string message = "")
{
AssertThat(anyObject, (T)actual, matcher, message);
}
public static void AssertThat<T, TSuper>(this object testFixture, T actual, Matcher<TSuper> matcher, string message = "") where T : TSuper
{
... check and assert
Consider the following method:
public bool IsNullString<T>(T item) {
return typeof(T) == typeof(string) && item == null;
}
Yes, this is a pathetically stupid method and using generics is pointless here, but you'll see the point in a moment.
Now consider
bool first = IsNullString<string>(null);
bool second = IsNullString<Foo>(null);
bool third = IsNullString(null);
In the first and second, the compiler can clearly distinguish the type of T (no inference is needed). In the third, how the compiler infer what T is? In particular, it can't distinguish between T == string and T == Foo, or any other type for that matter. Therefore, the compiler has to give you a compile-time error.
If you want to get around this, you either need to cast null
EqualTo((object)null);
or explicitly state the type
EqualTo<object>(null)
or define an overload
private static Matcher<object> EqualTo(object item) {
return new IsEqual<object>(item);
}
Not possible without explicitly specifying a T or doing a cast. Generics are compile time constructs and as such if the compiler can't figure out the type at compile time, then it won't compile (as you're seeing).
Since you can't do exactly what you are wanting to do, how about defining an EqualTo(object) overloaded method? That should allow your required syntax.
You may work around this limitation by using the following syntax:
EqualTo("abc");
EqualTo(4);
EqualTo(default(object));
//equivalently:
EqualTo((object)null);
default(T) is the value a field of type T has if not set. For reference types, it's null, for value types it's essentially memory filled with zero bytes (...which may mean different things for different types, but generally means some version of zero).
I try to avoid the null everywhere in my code nowadays. It hampers type inference elsewhere too, such as with the var declared field and in a ternary operator. For example, myArray==null ? default(int?) : myArray.Length is OK, but myArray==null ? null : myArray.Length won't compile.
Maybe implementing a non-generic EqualTo, which takes an Object as the argument type, would solve the issue of rewriting those code lines.

Construct AndAlso/OrElse LINQ expression with custom method

I'm trying to pass in a custom MethodInfo to the Expression.AndAlso and OrElse factory methods (which are for the && and || operators, respectively). These operators use short circuiting, which makes this difficult, but normally the & and | operators (along with the true and false operators) are used. However, the MSDN documentation for Expression.AndAlso/OrElse doesn't mention the true or false operators.
For testing, I've declared a method that uses a normal & operator on two ints:
public static int And(int a, int b) {
return a & b;
}
Note that the return type must be int rather than bool to avoid an exception.
I then construct the expression:
var expr = Expression.AndAlso(
Expression.Constant(0),
Expression.Constant(5),
new Func<int, int, int>(And).Method
);
This results in an exception:
The user-defined operator method 'And' for operator 'AndAlso' must have associated boolean True and False operators.
Strangely, the error is also thrown if I use a custom struct that has the true and false operators. I can avoid it if the struct overloads the & operator and I pass in that overload, but not if I pass in a different method. Other non-short-circuiting operators work with custom methods though.
The problem is that I don't know how to pass methods for the true and false operators in. I first thought I could maybe combine them as delegates, but the different methods have incompatible signatures. Is there any way to pass these methods in?
The bigger picture
I'm building a system for interpreting expressions to support ahead-of-time compilation. It supports using a custom method for the AndAlso/OrElse operators, currently by taking a custom Func<InterpretedExpression, InterpretedExpression, object> (which works as the expressions are interpreted rather than compiled). This could easily be changed if it causes problems (which would be due to it not having accessible true and false methods).
Note: I'm using Visual Studio's C# Interactive window for testing, but ultimately need to support .NET 3.5 (though information for newer versions is still helpful and appreciated).
The problem is that I don't know how to pass methods for the true and false operators in. I first thought I could maybe combine them as delegates, but the different methods have incompatible signatures. Is there any way to pass these methods in?
The short answer is no, you can't.
Looking at the reference source implementation (unfortunately, it should really be in the documentation), looks like the passed method has the following constraints:
(1) It should be a static non generic method with signature
static T Method(T arg0, T arg1);
where T cannot be an open generic type.
(2) The declaring type of the method must have operators true and false defined.
Since operators true and false require the argument type to be the same as the declaring type, this combined with (1) really constraints the usage to class/struct T declaring the static method and true and false operators.
In other words, a method with bitwise & / | operator semantics without actually overloading those operators.
So it can be used only for types like this:
public struct IntWrapper
{
public readonly int Value;
public IntWrapper(int value) { Value = value; }
public static IntWrapper And(IntWrapper a, IntWrapper b) { return new IntWrapper(a.Value & b.Value); }
public static bool operator true(IntWrapper x) { return x.Value != 0; }
public static bool operator false(IntWrapper x) { return x.Value == 0; }
}
with usage:
var expr = Expression.AndAlso(
Expression.Constant(new IntWrapper(0)),
Expression.Constant(new IntWrapper(5)),
new Func<IntWrapper, IntWrapper, IntWrapper>(IntWrapper.And).Method
);
This I guess limits more general usage you are after.

What is the common way to cast non-nullable or return default(Type)

Working with all the dictionaries within ASP.NET MVC (like RouteData, DataTokens etc), I often find myself wanting to do stuff like:
bool isLolCat = routeData["isLolcat"] as bool
that would return the casted value, or default (false in this case) when the value is null.
Is there any short, readable, simple way to do this, or am I better off writing a helper extension method?
An extension method would something like this.
bool isLolCat = routeData["isLolcat"].TryCast<bool>();
I rather don't want to reinvent the wheel with custom syntax if there is a common way to do this.
I don't want to litter my code with a few lines, when I just to try to get a bool out of a dictionary.
Maybe you like any of these:
(routeData["isLolcat"] as bool?).GetValueOrDefault()
(routeData["isLolcat"] as bool?).GetValueOrDefault(false)
(routeData["isLolcat"] as bool?) ?? false
If not you'll have to write a helper. I actually recommend using a helper because the code that I posted kind of obfuscates what you mean. I'd rather see this:
routeData.GetOrDefault<bool>("isLolcat")
Because this documents in writing what you intend.
Is there any short, readable, simple way to do this, or am I better off writing a helper extension method?
I'd say you would be better writing your own extension because you can make your intentions clear
public static class Ext
{
public static T CastOrDefault<T>(this object obj)
{
return obj is T ? (T)obj : default(T);
}
}
...
bool isLolCat = RouteData["isLolCat"].CastOrDefault<bool>();
Suggestion - If you wanted to keep it short, you could call it something like As<T>
bool isLolCat = RouteData["isLolCat"].As<bool>();
string str = RouteData["isLolCat"].As<string>(); // null
I don't think there's a most common way, all casting / conversion operations have their own idiosyncrasies.
For example, Convert.ToBool can accept strings to convert, do you want this to convert, or should this fail?
x as bool will give you null if it's not of type bool.
I think it would be best to write an extension method for RouteData.
public static T GetValueOrDefault<T>(this RouteData routeData, string field)
{
var value = routeData[field];
if (value is T)
{
return (T)value;
}
return default(T);
}
This way you're operating on the RouteData class and not potentially null values.
Usage:
var isLolCat = routeData.GetValueOrDefault<bool>("IsLolCat");

Can I cast an integer to a long when the types are generic/boxed?

The method below looks for a particular key in a dictionary and attempts to safely store it in destination if it can. The problem I am running into is when T=Int64 and the item in the dictionary is Int32 or UInt32 (both of which can fit inside an Int64 without data loss). valueAsObject is T returns false when T is Int64 and valueAsObject is Int32.
Is it possible to safely cast valueAsObject to T without just trying it and catching any exceptions? I would like to avoid exceptions, though if that is the only way I can make it work.
public static void MyMethod<T>(IDictionary<String, Object> dictionary, String key, ref T destination)
{
if (!dictionary.ContainsKey(key))
return;
var valueAsObject = dictionary[key];
if (!(valueAsObject is T))
return;
destination = (T)valueAsObject;
}
Basically, I want the function to do nothing (return) if the thing found in the dictionary can not be safely stored in a type T variable (without data loss), otherwise it should cast it as necessary and store it.
This is not built-in at the language or runtime level. You can use Convert.ChangeType to perform the conversion. This method also performs lossy conversions so you probably have to build your own conversion logic (which will involve casts and be ugly).
You can't just do something like this?
public static void MyMethod<T>( IDictionary<string,object> dictionary , string key , ref T destination )
{
object value ;
bool found = dictionary.TryGetValue( key , out value ) ;
if (found && value is T)
{
destination = (T) value ;
}
return;
}
The is operator:
evaluates to true if the provided expression is non-null, and the provided object
can be cast to the provided type without causing an exception to be thrown.
.
.
.
Note that the is operator only considers reference conversions, boxing conversions,
and unboxing conversions. Other conversions, such as user-defined conversions, are not considered.
Basically, if the object directly inherits from the specified type, or implements the type (if T is an interface), is should return true and you should be able to down-cast the object to your type T.
If, however, you need to worry about user-defined conversion operators, you'll need to reflect over the object's type and over typeof(T) to see if a user-defined conversion operator is defined on either type that will convert the object to a compatible type. Getting that right is likely to be...tricky.
This is the final solution I went with. It came from a number of comments and other answers so I encourage reading the other answers/comments for additional details as to why this was necessary:
private static void GetFromDictionary<T>(IDictionary<String, Object> dictionary, String key, ref T outputLocation)
{
if (!dictionary.ContainsKey(key))
return;
var valueAsObject = dictionary[key];
if (!CanBeCastTo<T>(valueAsObject))
return;
outputLocation = (T)Convert.ChangeType(valueAsObject, typeof(T));
}
private static bool CanBeCastTo<T>(Object thingToCast)
{
if (thingToCast is T)
return true;
var tType = typeof(T);
if (tType == typeof(Int64) && thingToCast is Int32)
return true;
if (tType == typeof(Double) && thingToCast is Decimal)
return true;
return false;
}
In my case, I only needed to handle a certain subset of primitive types (Int32, Int64, String, Double, Decimal) and I was willing to accept lossy conversion of Decimal to Double.
The take away here is that the "is" operator will return false for primitives even if it can fit without loss (Int32 in Int64). Also, (T)valueAsObject will not do an explicit typecast. So if valueAsObject is of type Int32 and T is of type Int64 the above will throw an exception even though (Int64)valueAsObject is valid. This one bit me but luckily #usr suggested using Convert.ChangeType which handles the problem.
Optimizations could be made to the above code but I chose to leave it as is for readability.

Categories

Resources