Say I have a class
class T
{
int num;
public T(int num)
{
this.num = num;
}
public void p()
{
Console.WriteLine(this.num);
}
}
And I have a null object T t = null. Calling the method t.p() will cause a NullReferenceException no matter what.
Is it not possible to test if the object is null (by using this == null (to check if the object is null within the method)), so is there a way to set a default method that will work on a null object?
In whatever code that calls t.p() you should check if t is null. You shouldn't be calling methods on a null instance.
Regarding the second part of your question, no it is not possible to set a default method that will be called if the instance of that object is null.
I should point out that there is also the Null Object Pattern, that, depending on the exact circumstances of usage may help. I would not use it as replacement for null checks though. I've found the pattern useful in some cases.
In C/C++ you can do this, but not (easily) in C#.
For example, you might want to have a check for "if a string is empty" or "if a collection is empty", and treat a null object as meaning "empty". For this sort of case, being able to call an IsEmpty() method via a null pointer/reference results in what seems like more elegant/readable code:
if (myList.IsEmpty())
...
rather than
if (myList == null || myList.IsEmpty())
...
However, it is also extremely dangerous as it hides unusual/unexpected behaviour, and encourages the caller to stop checking for nulls. As you cannot guarantee that every method you call will protect you from nulls, how do you know that it is safe to stop checking for nulls in the calling code? Or do you check for null twice (in both the calling and called code), just in case? If you are calling many methods on the same object instance, wouldn't it be far more efficient to check for null once at the start?
So although this pattern can be used in some languages, it is not considered a good practice.
This is (one reason) why, in C#, such code is not allowed. Instead the preferred pattern is to provide a static method to check the status:
if (string.IsNullOrEmpty(myString))
....
This is only slightly less readable, but much safer as the null check is clearly visible to the reader. Even without "IsNull" in the title, tou can see that the reference is being passed to another method, and it is more reasonable to assume that the called method will be well written and check for nulls. Being transparent and explicit makes code much easier for others to read.
C# also provides the null coalescing ?? operator to make the null checks cleaner in the calling code. If you want a default to use if the object is null, then you can use this form:
string result = myString ?? string.Empty;
...which in this case will return myString if it is non-null, or string.Empty if it is null, thus guaranteeing that result is never null.
Finally, in C# 6 you can use the ?. operator, which combines an "if not null" check with an access, so you can replace:
if (element != null && element.FirstChild != null)
element.FirstChild.DoSomething();
with
element?.FirstChild?.DoSomething();
This is functionally equivalent, but a much more compact syntax.
Calling an instance method on a null reference will always result in a NullReferenceException. You have to check if the reference is not null or use the C# 6 ?. operator to do it for you.
T t = null;
t?.p(); // no method is called
You can however use an extension method on a null reference. It has some limitations, as you can only access public members in an extension method, but might be useful (especially if you cannot use C# 6 and ?.):
class T
{
public int Number { get; private set; } // public property
public T(int number)
{
Number = number;
}
}
static class Extensions
{
public static void PrintT(this T t)
{
if (t == null) Console.WriteLine("null");
else Console.WriteLine(t.Number);
}
}
T t = null;
t.PrintT(); // no exception, writes "null" to the console
It is possible to call an instance method on a null reference in CIL, simply using call instead of callvirt. The latter checks the run-time type of the referenced object, that's why it throws NRE immediately. call should call the method normally, but with the implicit this parameter set to null, and throw on first access to any member of this.
Edit
The System.Reflection.Emit namespace in C# contains types that let you dynamically emit IL. You can use it to call an instance method with a call instead of callvirt. (I modified code posted in this answer to work for methods. The sample here will only work for parameterless methods)
public static void MakeNonVirtualCall<T>(T c, Expression<Action<T>> f)
{
var expression = f.Body as MethodCallExpression;
if (expression == null) throw new ArgumentException();
var dyn = new DynamicMethod("NVCall", null, new[] { typeof(T) }, typeof(T).Module, true);
var il = dyn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, expression.Method);
il.Emit(OpCodes.Ret);
((Action<T>)dyn.CreateDelegate(typeof(Action<T>)))(c);
}
Now, assuming we have a class
class Class
{
public void Method()
{
if (this == null) Console.WriteLine("`this` is null");
else Console.WriteLine("`this` is not null");
}
}
We can use it as
Class nullRef = null;
Class instance = new Class();
MakeNonVirtualCall(nullRef, t => t.Method()); // no exception, prints "`this` is null"
MakeNonVirtualCall(instance, t => t.Method()); // prints "`this` is not null"
It works - an instance method in a C# class can be called on a null reference from IL (but still not directly from C#).
Note that the MSDN documentation is incorrect here:
Calls to an instance (or virtual) method must push that instance reference before any of the user-visible arguments. The instance reference must not be a null reference.
Just check for null in the calling code.
T t = null;
// somewhere further..
if (t == null)
//t is null, don't use it
else
//save to use t
Another way (if you don't expect the object to be null is to use try/catch):
T t = null;
// somewhere further..
try {
t.p();
}
catch(NullReferenceException ex) {
// t is null
}
No you can't. And I'll tell you why. The keyword this refers to whichever object is accessing a variable or calling a method. So a this inside doSomething() would refer to object in object.doSomething().
Now coming to your question about null, when you write T t = null; it means you made a variable of type T which REFERS to NOTHING!!! And by nothing I mean, wait for it, NOTHING! Can you call methods from nothingness? NO!
Related
As far as I knew, Object.GetType() should never return null. (related discussion)
Dapper .Query() return private class DapperRow instances to be treated as dynamic objects. I found a strange thing: DapperRow's .GetType() return null.
Here's the sample code to reproduce the problem. Create a C# project, reference Dapper and open a connection to SQL Server (or other database), use .Query() to execute simple select query and retrieve the first row of result. Use GetType() to get the type of result object, the return value is null.
using (SqlConnection cn = new SqlConnection(csSql))
{
var rec = cn.Query("select getdate() as D").Single();
var t = rec.GetType(); // t == null
Console.WriteLine(t.Name); // null reference exception
}
I suspect that dynamic or private type is the cause of null, so I write my class library for test:
namespace Lib
{
public class Blah
{
public static dynamic SecretObject;
static Blah()
{
SecretObject = new PrivateType();
}
}
class PrivateType
{
}
}
In another project, get the dynamic type static field and call GetType():
dynamic obj = Lib.Blah.SecretObject;
Console.WriteLine(obj.GetType().Name); // "Lib.PrivateType"
According to the test result, even cast private type as dynamic, I still can get the private type information from GetType(), why DapperRow.GetType() return null?
DapperRow is specifically built and utilized within Dapper to provide highly optimized row returns without reiterating header information. This is to help condense the size of the object and reduce redundant data, making it more efficient.
However, it would appear that the StackExchange team took the meta programming even further than a first glance would indicate.
DapperRow implements the System.Dynamic.IDynamicMetaObjectProvide interface, which requires that the GetMetaObject method be implemented:
System.Dynamic.DynamicMetaObject System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(
System.Linq.Expressions.Expression parameter)
{
return new DapperRowMetaObject(parameter,
System.Dynamic.BindingRestrictions.Empty, this);
}
DapperRowMetaObject is a custom implementation of DynamicMetaObject that essentially hijacks and overrides what methods can be invoked against the dynamic type and what those calls should translate to. In this case, calls to anything other than the DapperRow's IDictionary.Item getter or the DapperRow.SetValue will fail since they are always routed to those two calls, but the value will be defaulted to null for any "get" calls where the target property does not exist in the table.
public bool TryGetValue(string name, out object value)
{
var index = table.IndexOfName(name);
if (index < 0)
{ // doesn't exist
value = null;
return false;
}
...
}
At that point, any methods invoked on a null dynamic value will throw a RuntimeBinderException:
RuntimeBinderException: Cannot perform runtime binding on a null
reference
You can easily test this hypothesis by replacing GetType() with another call that will throw the exact same exception:
var rec = cn.Query("select getdate() as D").Single();
var t = rec.AsEnumerable();
Console.WriteLine(t.ToList());
Keep in mind, the underlying type information of any properties on the dynamic object itself can still be accessed directly:
var rec = cn.Query("select getdate() as D").Single();
var t = rec.D.GetType();
Console.WriteLine(t.Name);
Right now I am working on a simple program, and this is a problem I've been thinking over many times. Many times I run my methods twice because of checking on the return value before running them, and I would like to know if there is a way I can prevent this, like using the returned value from the method I am checking against. It's quite hard to explain so here is a real life example from my program.
public class SFDBRepository
{
public static Domain.SF.SFObject GetSFOrder(string WorkOrd)
{
//As you can see here i'm checking on the output of this method, before trying to return it.
if (Domain.SF.SF.GetOrder(WorkOrd) != null)
{
//If the value is not null (My method returns null if no result), return the object
return Domain.SF.SF.GetOrder(WorkOrd);
}
//Same thing happens here. My method runs twice every time almost.
else if(Domain.Building_DeliveryPerformance.Building_DeliveryPerformance.GetObject(WorkOrd) != null)
{
return Domain.Building_DeliveryPerformance.Building_DeliveryPerformance.GetObject(WorkOrd);
}
else
{
return null;
}
}
}
You can simplify this down to the following code, which will only call those methods once and make the code much more readable:
public class ShopFloorDBRepository
{
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string workOrd)
{
return Domain.ShopFloor.Shopfloor.GetOrder(workOrd) ??
Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(workOrd);
}
}
To explain why this works - the ?? operator (the null-coalescing operator!) basically says "if the returned value on the left hand side of the ?? is null, then return the value of the expression on the right hand side".
This way you only need to call your functions once.
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
//As you can see here i'm checking on the output of this method, before trying to return it.
Domain.ShopFloor.ShopFloorObject wo = Domain.ShopFloor.Shopfloor.GetOrder(WorkOrd);
if (wo != null)
{
//If the value is not null (My method returns null if no result), return the object
return wo;
}
//Same thing happens here. My method runs twice every time almost.
Domain.ShopFloor.ShopFloorObject yowo = Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(WorkOrd);
if(yowo != null)
{
return yowo;
}
/* default return */
return null;
}
PS
You're kinda doing the "Factory Pattern"
See
http://www.dofactory.com/net/factory-method-design-pattern
Looks to me like you could be using a temporary variable to hold the result, which you can test and return.
public class ShopFloorDBRepository
{
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
var result = Domain.ShopFloor.GetOrder(WorkOrd);
if (result != null) return result;
...
This is a common paradigm, especially when the method being called is expensive and/or has side effects you don't wish to incur twice.
Here, the "var" declaration sets the type of "result" to the type returned by the method being called; you could also use the name of the actual type.
If you wish to make two different kinds of tests like this, you'll need two different variables unless they have the same type (which in this case it appears they do).
An alternate mechanism that does require the full type, that you'll also see:
public static ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
ShopFloorObject result;
if ( (result = Domain.ShopFloor.GetOrder(WorkOrd)) != null )
return result;
if ( (result = Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(WorkOrd)) != null)
return result;
return null;
Here you're explicitly declaring the type of the return value, then making the two calls you've indicated, testing the results against null, and returning the first non-null value.
I have an initial snippet which deserealized parameters, checks for value and handles the error:
var param = js.Deserialize<int?>(jqData.Params);
if (param.HasValue)
{
resp.ReturnValue = param.Value;
}
else
{
//handle error code
}
Now, during my modification, I have changed the method to accept a list of class parameters instead of nullable integers
var param = js.Deserialize<ClassName>(jqData.Params);
Now it invalidates .HasValue and .Value methods.
My question is: How do I properly modify these two lines so it would hold the same meaning as initial if statement?
Thus far I only thought about switching to if (param != null), but I cannot think of proper equivalent to .Value.
As soon as ClassName is a class (see - a reference type) you just need to check if it is not null.
If it is not - then the variable holds a reference to an object that you use as-is.
I have the following code
class Program
{
static void Main()
{
A a = new A();
a.M(null);
}
}
class A
{
public void M(int? i)
{ }
public void M(string s)
{ }
}
And I have an error, because the call is ambiguous. I need to change the call of M method without adding any lines to Main method and accessing class A so that it became correct. Could someone please tell me how to do this?
You can use explicit cast:
A a = new A();
a.M((string)null);
or
a.M((int?)null);
to help the compiler of picking the right overload. Note that C# compiler can't determine what method overload to call based on null literal.
For advanced topic consider Eric's article What is the type of the null literal?
edit:
since your argument names are different, you can use named arguments, which are avaliable since C# 4.0:
a.M(i : null);
or
a.M(s : null);
You can use a cast, or the default keyword, or for int?, new int?() (which, due to how Nullable types work, is also the same as null). You could also use named parameters to disambiguate. Or, of course, if you were ok with adding another line, you could declare your value in a variable and pass that in.
// these call the int? overload
a.M(default(int?));
a.M((int?)null);
a.M(new int?());
a.M(i: null);
int? i = null;
a.M(i);
// these call the string overload
a.M(default(string));
a.M((string)null);
a.M(s: null);
string s = null;
a.M(s);
The answer is that you cannot overload the member M this way if you cannot alter existing call sites.
Presumably you are adding one of the two methods and can alter the call sites for calls to the new method. Change the name of the method for those new call sites to use.
In a class of mine, I have a private field of type ExpandoObject. The field is initialized in the constructior (this.expected = new ExpandoObject()), so I'm confident that it will never be null.
Thus, in one of the methods on this class, I fell safe to add
Contract.Assumes(this.expected != null)
before using this.expected for anything, so Code Contracts won't have to worry about possible calls on null objects. However, instead of a warning for possible method call on a null reference, I get a warning saying
The dynamically dispatched call to method 'Assume' may fail at runtime because one or more applicable overloads are conditional method
The method signature and the first few lines of code looks like this:
protected void Expect(object values)
{
Contract.Requires<ArgumentNullException>(values != null);
Contract.Assume(this.expected != null);
var exp = (ICollection<KeyValuePair<string, object>>)this.expected;
On the third line, I get a warning for
CodeContracts: Possibly calling a method on a null reference 'OddEnds.Testing.TestBase.o_SiteContainer0.<>p_Site3.Target'
where I assume the odd signature of the null reference is because exp is a dynamic object.
How do I solve these?
I think the best way to solve your problem is to declare that expected is never null as an invariant on the class:
class TheClass {
ExpandoObject expected;
...
[ContractInvariantMethod]
void Invariants()
{
Contract.Invariant(this.expected != null);
}
...
}
When you do this, the static checker will check that expected is not null at the end of your constructor, and then it will know that expected is never null at the start of any other method.
Im thinking following code change will keep compiler happy (if your sure in this cast anyway, but why use expandoobject then.. anyway)
ICollection<KeyValuePair<string, object>> col = this.expected as ICollection<KeyValuePair<string, object>>;
Contract.Assume(col != null);