Creating an instance of a class using the extension method

The idea behind this code is that it uses an extension method to instantiate the class if this class is set to null. The code is simple enough, but it doesn’t work (it compiles and runs, but at the end the reference to the object is still null ).

Can someone tell me why?

The following code uses the simple SomeClass class, which has one 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?? } } 

(A discussion of the appropriateness of using the extension method should be considered outside the scope of the question! I am interested to understand why this approach does not work)

Edit

On closer inspection, this question is less about extension methods and more about what happens when you pass a reference type with or without the ref keyword.

The following function will initialize the past obj 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 initialize the past obj 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 are dealing with a reference type here, so what does the CLR do with new d obj if the ref keyword is not used? Presumably, he just gets the garbage collected ...

Edit2

Ok, we will get back to the basics here. Consider the following code:

 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 not passed using the ref keyword, but its property value was still changed for the caller. This is what I expect to see.

However, modify the SetProperty function as follows:

 static void SetProperty(SomeClass someClass) { someClass = new SomeClass { SomeProperty = "Bar" }; } 

... and the caller will not see any changes in SomeClass .

+4
source share
4 answers

this T obj must be a ref argument. Since this is not allowed ( MSDN or C # In Depth p258, Skeet), you cannot.

I would suggest that you are not promoting this idea too much. This seems like a confusing application of extension methods, especially when the alternative is still a short single line.

+5
source

You will need to return the value; extension methods are not ref in this argument:

 static class ExtensionMethods { public static T InitialiseObjectIfNull<T>(this T obj) where T : class, new() { return obj ?? new T(); } } 

Then you will need:

 someClass = someClass.InitialiseObjectIfNull(); 

Personally, I expect it would be easier to do this directly ... with:

 if(someClass == null) someClass = new SomeClass(); 

or

 someClass = someClass ?? new SomeClass(); 
+6
source

The extension method is just syntactic sugar:

 ExtensionMethods.InitialiseObjectIfNull(someClass); 

You pass someClass by value, so assigning it inside the InitialiseObjectIfNull body will not have effect unless you pass someClass to a link that you cannot do with extension methods: you cannot pass this to this T obj by reference.

+4
source

This does not work because the obj parameter is not declared passed by reference. Unfortunately, you cannot declare the parameter as "this ref T obj", it is not supported ... I know, I tried this yesterday;)

Instead, you can do something like this:

 static class ExtensionMethods { public static T InitialiseObjectIfNull<T>(this T obj) where T : class, new() { return obj ?? new (); } } class SomeClass { public string SomeProperty { get; set; } } class Program { static void Main(string[] args) { SomeClass someClass = null; someClass = someClass.InitialiseObjectIfNull(); } } 
+2
source

All Articles