what is the point of allowing invocation of extension methods on null objects?
this is making me unnecessarily check for a null object in the extension method.
AFAIK,i can't understand this?
Please explain.
Extension methods are syntactic sugar of the C# language, they get compiled to normal static method calls in ILCode. A static method doesn't know anything about the parameters at compile time.
Simply put, why not?
You can sometimes skip the test if the first method you call within the extension would also throw the correct error.
You're essentially asking for the code to be different so that:
Uses which are reasonable on a null object, become disallowed.
Uses which don't need a null check (because it's implicit in something else) get the overhead of the needless check you want to happen automatically.
This seems a lot of an imposition on other uses just to save the one line of:
if(arg == null)throw new ArgumentNullException();
Extension methods are just syntactic sugar. In reality they are static methods on another class, so since you can write
IEnumerable<int> foo = null;
Enumerable.Count(foo);
You can also write
IEnumerable<int> foo = null;
foo.Count();
Sometimes, allowing the extension method to be called on a null object simplifies your code by allowing you to move the null check into the method instead at the call site. For example, you may have an extension method that returns a List<T>, but if called on a null object, returns an empty List<T>.
Extension methods are transformed to static method invocations so the code will still need to check for null arguments as there is no way to avoid the static method to be called normally without the extension method syntactic sugar.
Adding something like a check followed by a NullArgumentException could take execution time and the user may want to assert instead or use something else.
It would make the replacement more complex to explain or do automatically as the simple replacement of the extension method with the corresponding static method call will change the behavior of the code.
There are legitimate case where you want to allow null arguments (for exemple conversions from an object model to another where a null object of one type is converted to a null object of the second type)
Extension methods are just static methods:
List<int> x = null;
x.Count()
Is equivalent to:
List<int> x = null;
System.Linq.EnumerableExtensions.Count(x);
//EnumerableExtensions may not be the class, but you get the idea
Another beautiful example that wouldn't be possible otherwise:
public static bool IsNullOrEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
So you can use
string s = null;
if (s.IsNullOrEmpty()) // no null reference error!
...
Instead of
string s = null;
if (string.IsNullOrEmpty(s))
....
Related
When you extend a non-static type with an extension method, does the work performed on "this" happen to the original instance of the extended class, or does it return a new instance with those changes applied? Or can it do either, depending on how the extension method is written?
Consider this example extension method:
public static AddressEntity FromAddressLight(this AddressEntity addressEntity, AddressLight addressLight)
{
if (addressLight == null)
{
return null;
}
var result = new AddressEntity
{
Id = addressLight.AddressId,
AddressName = addressLight.AddressName,
// other mapping conversions here
};
return result;
}
Which of the following ways of calling this would work?
AddressLight light = new AddressLight(); // assume constructor populates this
AddressEntity myEntity = new AddressEntity(); // this constructor does not populate anything
myEntity.FromAddressLight(light); // Will this cause myEntity take on the value of "result" in the extension method?...
myEntity = myEntity.FromAddressLight(light); // ... or is this needed to copy "result" into myEntity?
// ... and why is this not something Visual Studio allows? Does this not become a static member of the extended class?
myEntity = AddressEntity.FromAddressLight(light);
Quick Answer... It Depends.
The example you give returns a new instance of AddressEntity but there's no reason it can't return the same instance which is handy for chaining or something completely different.
It's up to you.
myEntity = myEntity.FromAddressLight(light); is the correct use of this method in your example.
And myEntity = AddressEntity.FromAddressLight(light); doesn't work because you're calling a static method not an instance method even though this is a little counter-intuitive given the static declaration.
Thats kind of odd as an extension method (makes more sense as a "normal" static method) but here goes, In order of your lines (skipping the first two):
This will do nothing. The extension method returns a new object, which is not assigned to anything, and so falls out of scope and is garbage collected.
This will do exactly what you think, and is the only "reasonable" way to use this method.
This isn't allowed because there is no instance of "AddressEntity" being passed to the function. Not explicitly (obviously you only pass 1 argument) or implicitly (because you used the type to access it, not an object).
Especially because you are trying to do (3), I would not have this function as an extension method (it doesn't even use any of the AddressEntity field, so why does it take that type?) and have it be a normal static method instead.
To answer your question (in the title) explicitly:
An extension method isn't anything special, it just has an implicit argument (the "this" argument) so it looks nice when calling it. If it returns a new value, you'll get a new value. If you modify the "this" argument, it modifies the existing value. It could actually do both with no problem. It completely depends on the content of the extension method.
This is pretty odd as an extension method, in general. Consider that the extension method is just syntactic sugar (as was previously mentioned by others), and that a normal user would really be expecting one of two things to happen:
I call the extension method and get a modified version of myself back.
I call the extension method and get a converted type back.
I think number two is what you really want:
public static AddressEntity ToAddressEntity(this AddressLight obj)
{
return new AddressEntity
{
Id = obj.AddressId,
AddressName = obj.AddressName,
// other mapping conversions here
};
}
Remember that extension methods are not based on the return type but on the type specified after this. So in this case you can just do AddressEntity addEntity = SomeAddressLight.ToAddressEntity();. This is also the reason you don't see the pattern FromSomething() in any of the BCL because in the case of an extension method it feels very counterintuitive.
I'm trying to write a generic method that will return specific markup when passed an enum. Below is the method which has been reduced to the minimum required code for this question.
public static string GetMarkup(Type enumType)
{
StringBuilder builder = new StringBuilder();
foreach (var val in Enum.GetValues(enumType))
{
builder.Append(val.ToString());
}
return builder.ToString();
}
The method is called like this where CopyType is an enum:
GetDropDownListHtml(typeof(CopyType))
The goal is to be able to call ToString() extension methods I've written for the enums I'll pass into this method. The problem is that to make the method generic, I need to use var to declare my variable in the foreach declaration, but that boxes it. Instead of an enum of CopyType, I have an object that is the boxed CopyType.
In response, I've tried many thinks like this, but to no avail:
((typeof(enumType))val.ToString()
Any ideas?
There's no way to use extension methods to do this to a specific enum. You either need to extend your extension method to support all Enum types, add an is statement in there which you can use to only cast it when necessary, or write a special overload to this function which you call just for this type of enum. This has to do with how extension methods are actually implemented.
The compiler turns an extension method into its static form: myCopyType.ToString() becomes CopyType.ToString(myCopyType) when compiled. But with your scenario (or even with generics) the compiler can't tell what type to use, because the type isn't determined until runtime.
This leaves the three choices above.
In my own code, I went with the first option, based on the code here. You'll be able to call .GetLabel() on any Enum type, and you can put your special labels on this one specifically.
Additionally, you'll need to use foreach (Enum val in ... instead, so as to make sure the compiler knows it's an Enum.
I've always thought that it's impossible for this to be null inside instance method body. Following simple program demonstrates that it is possible. Is this some documented behaviour?
class Foo
{
public void Bar()
{
Debug.Assert(this == null);
}
}
public static void Test()
{
var action = (Action)Delegate.CreateDelegate(typeof (Action), null, typeof(Foo).GetMethod("Bar"));
action();
}
UPDATE
I agree with the answers saying that it's how this method is documented. However, I don't really understand this behaviour. Especially because it's not how C# is designed.
We had gotten a report from somebody (likely one of the .NET groups
using C# (thought it wasn't yet named C# at that time)) who had
written code that called a method on a null pointer, but they didn’t
get an exception because the method didn’t access any fields (ie
“this” was null, but nothing in the method used it). That method then
called another method which did use the this point and threw an
exception, and a bit of head-scratching ensued. After they figured it
out, they sent us a note about it.
We thought that being able to call a method on a null instance was a
bit weird. Peter Golde did some testing to see what the perf impact
was of always using callvirt, and it was small enough that we decided
to make the change.
http://blogs.msdn.com/b/ericgu/archive/2008/07/02/why-does-c-always-use-callvirt.aspx
Because you're passing null into the firstArgument of Delegate.CreateDelegate
So you're calling an instance method on a null object.
http://msdn.microsoft.com/en-us/library/74x8f551.aspx
If firstArgument is a null reference and method is an instance method,
the result depends on the signatures of the delegate type type and of
method:
If the signature of type explicitly includes the hidden first
parameter of method, the delegate is said to represent an open
instance method. When the delegate is invoked, the first argument in
the argument list is passed to the hidden instance parameter of
method.
If the signatures of method and type match (that is, all parameter
types are compatible), then the delegate is said to be closed over a
null reference. Invoking the delegate is like calling an instance
method on a null instance, which is not a particularly useful thing to
do.
Sure you can call into a method if you are using the call IL instruction or the delegate approach. You will set this booby trap only off if you try to access member fields which will give you the NullReferenceException you did seek for.
try
int x;
public void Bar()
{
x = 1; // NullRefException
Debug.Assert(this == null);
}
The BCL does even contain explicit this == null checks to aid debugging for languages which do not use callvirt (like C#) all the time. See this question for further infos.
The String class for example has such checks. There is nothing mysterious about them except that you will not see the need for them in languages like C#.
// Determines whether two strings match.
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public override bool Equals(Object obj)
{
//this is necessary to guard against reverse-pinvokes and
//other callers who do not use the callvirt instruction
if (this == null)
throw new NullReferenceException();
String str = obj as String;
if (str == null)
return false;
if (Object.ReferenceEquals(this, obj))
return true;
return EqualsHelper(this, str);
}
Try the documentation for Delegate.CreateDelegate() at msdn.
You're "manually" calling everything, and thus instead of passing an instance in for the this pointer, you're passing null. So it can happen, but you have to try really really hard.
this is a reference, so there is no problem with its being null from the perspective of the type system.
You may ask why NullReferenceException was not thrown. The full list of circumstances when CLR throws that exception is documented. Your case is not listed. Yes, it is a callvirt, but to Delegate.Invoke (see here) rather than to Bar, and so the this reference is actually your non-null delegate!
The behavior you see has an interesting implementational consequence for CLR. A delegate has a Target property (corresponds to your this reference) that is quite frequently null, namely when the delegate is static (imagine Bar be static). Now there is, naturally, a private backing field for the property, called _target. Does _target contain a null for a static delegate? No it doesn't. It contains a reference to the delegate itself. Why not null? Because a null is a legitimate target of a delegate as your example shows and CLR does not have two flavors of a null pointer to distinguish the static delegate somehow.
This bit of trivium demonstrates that with delegates, null targets of instance methods are no afterthought. You may still be asking the ultimate question: but why they had to be supported?
The early CLR had an ambitious plan of becoming, among others, the platform of choice even for sworn C++ developers, a goal that was approached first with Managed C++ and then with C++/CLI. Some too challenging language features were omitten, but there was nothing really challenging about supporting instance methods executing without an instance, which is perfectly normal in C++. Including delegate support.
The ultimate answer therefore is: because C# and CLR are two different worlds.
More good reading and even better reading to show the design allowing null instances shows its traces even in very natural C# syntactic contexts.
this is a readonly reference in C# classes. Accordingly and as expected this can be used like any other references (in read only mode) ...
this == null // readonly - possible
this = new this() // write - not possible
If I have a long list of objects that each has the possibility of returning null within a "Linq where" clause, e.g.
SomeSource.Where(srcItem=>(srcItem.DataMembers["SomeText"].Connection.ConnectedTo as Type1).Handler.ForceInvocation == true));
the indexer can return null and the "as" operator may return null. It is possible that the object does not have a connection (ie. The property is null).
If a null is encountered anywhere, I would like the where clause to return "false" for the item being evaluated. Instead, it aborts with a null reference exception.
It appears to me that this would be contrived to express within a single C# expression. I don't like to create a multi line statement or create a separate func for it.
Is there some use of the null coalescing operator that I'm missing?
You're looking for the .? operator (or is it ?.—one of those, anyway), which does not exist in C# (though it is an often-requested feature, according to Eric Lippert).
The only possible suggestion I have is to write a method that takes an expression and uses it to check for any nulls. But this will come at a performance cost. Anyway, it might look like:
T TryOrDefault<T>(Expression<Func<T>> expression)
{
// Check every MemberExpression within expression one by one,
// looking for any nulls along the way.
// If a null is found, return default(T) or some default value.
// Otherwise...
Func<T> func = expression.Compile();
return func();
}
Using the andand operator from Ruby as inspiration, you could create an extension method that acts as a null guard.
public static U AndAnd<T, U>(this T obj, Func<T, U> func)
{
return obj == null ? default(U) : func(obj);
}
Your original code could then be rewritten as follows:
SomeSource.Where(srcItem => (srcItem.AndAnd(val => val.DataMembers["SomeText"]).AndAnd(val => val.Connection).AndAnd(val => val.ConnectedTo) as Type1).AndAnd(val => val.Handler).AndAnd(val => val.ForceInvocation));
Do be careful when returning non-boolean value types using this method - make sure you are familiar with the values returned by default(U).
create a separate func for it
This is the way to go. Do not be allergic to proper techniques. Methods you create are no more expensive (at runtime, and conceptually) than anonymous methods.
A while ago I wrote a project that mimics AndAnd that relies on DynamicProxy. It works fine, although I've not used it in prod. The only drawback is that it requires all of the members to be virtual or the returned types to be an interface so DynamicProxy can do its magic.
Check it here
https://bitbucket.org/mamadero/andand/overview
I'm used to seeing old code like
if (true)
{
...
}
where it's intuitively clear that someone was being either lazy or overly cautious when making a change. I ran across this snippet today, and I'm curious whether there's a functional difference between doing type comparison this way:
private static bool logField(Type t, string fieldname)
{
if (t.ToString() == typeof (Property).ToString())
{
...
}
return true;
}
and doing it this way:
private static bool logField(Type t, string fieldname)
{
if (t == typeof (Property))
{
...
}
return true;
}
I'd say that's generally laziness - but it may not be. For example, you could have two Property types, in the same effective file, but different copies. If typeof(Property) loads it from one file but t is loaded from a different one, your replacement would say they were different but the original code would compare say they were the same.
It's definitely an edge case, and one that you normally want to avoid in the first place... but it's just possible.
I can't think of any good reasons.
In fact, the former will throw if t is null.
The first one compares references of Strings, while the second one actually checks to see if t is of the Property type.
The first one will always be "correct" because the two strings refer to the same object, but the second one is the correct way to check if t is of the Property type.
An equivalent and more readable way to do a type check is
if (t is Property)
No, getting the type object of 2 instances of the same type will always return a reference to the same type object in memory. This means that performing a reference equality check (==) is sufficient.
Essentially, calling:
if (t.ToString() == typeof (Property).ToString())
will call ToString() twice on the same object, where t is the 'Property' type.
I'd say that the first approach was probably done by someone unfamiliar with C#, not necessary being lazy. The string comparison will work for a majority of the time, except:
If t is null it would throw a null reference exception.
It doesn't take namespaces into consideration.
I would recommend the second case, unless you fall into needing the #2 edge case.