The idea behind this code is that it uses an extension method to instantiate an instance of a class if that class is set to null. The code is simple enough, but does not work (it compiles and runs, but at the end the object reference is still null
).
Can anyone suggest why?
The following code uses a simple class SomeClass
that has a single string
property.
class SomeClass
{
public string SomeProperty { get; set; }
}
static class ExtensionMethods
{
public static void InitialiseObjectIfNull<T>(this T obj)
where T : class, new()
{
if (obj == null) obj = new T();
}
}
class Program
{
static void Main(string[] args)
{
SomeClass someClass = null;
someClass.InitialiseObjectIfNull();
// someClass is still null - but why??
}
}
(The discussion about whether or not this is an appropriate use of an extension method should be considered outside the scope of the question! I am interested in understanding why this approach does not work)
On closer inspection this question is less about extension methods, and more about what is going on when you pass a reference type with or without the ref
keyword.
The following function will cause a passed obj
to be initialised for the caller:
static void InitialiseObjectIfNull<T>(ref T obj) where T : class, new()
{
if (obj == null) obj = new T();
}
InitialiseObjectIfNull<SomeClass>(ref someClass); // someClass will be initialised
The following function will not cause a passed obj
to be initlaised for the caller:
static void InitialiseObjectIfNull<T>(T obj) where T : class, new()
{
if (obj == null) obj = new T();
}
InitialiseObjectIfNull<SomeClass>(someClass); // someClass will not be initialised
But...we're dealing with a reference type here, so what does the CLR do with the new
d obj
if the ref
keyword is not used? Presumably it just gets garbage collected...
OK, we're going back to basics here. Consider the code below:
class Program
{
static void SetProperty(SomeClass someClass)
{
someClass.SomeProperty = "Bar";
}
static void Main(string[] args)
{
SomeClass someClass = new SomeClass { SomeProperty = "Foo" };
SetProperty(someClass);
// someClass.SomeProperty now equals "Bar"
}
}
Note: someClass
was not passed using the ref
keyword, but the value of its property was still changed for the caller. This is what I would expect to see.
However, change the SetProperty
function as follows:
static void SetProperty(SomeClass someClass)
{
someClass = new SomeClass { SomeProperty = "Bar" };
}
...and the caller will not see any change to someClass
.
You would need to return the value; extension methods aren't ref
on the this
argument:
static class ExtensionMethods
{
public static T InitialiseObjectIfNull<T>(this T obj)
where T : class, new()
{
return obj ?? new T();
}
}
Then you'd need:
someClass = someClass.InitialiseObjectIfNull();
Personally, I expect it would be simpler to do it directly... with either:
if(someClass == null) someClass = new SomeClass();
or
someClass = someClass ?? new SomeClass();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With