Why does HasFlag extension method on Enum trump Enum.HasFlag? - c#

If I create an extension method on Enum called HasFlag, whenever I try to call HasFlag on an enum instance, it uses the extension method, rather than the instance method. Why?
public static class Extensions
{
public static bool HasFlag(this Enum e)
{
return false
}
}
With code:
public enum Foo
{
A, B, C
}
public void Whatever()
{
Foo e = Foo.A;
if (e.HasFlag())
{
// ...
}
}
Compiles to:
public void Whatever()
{
Foo e = Foo.A;
if (Extensions.HasFlag(e))
{
// ...
}
}
Why doesn't the compiler use the Enum.HasFlag instance method?

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.
Extension methods cannot be override on instance main methods and it will not know which method to call:
The call is ambiguous between the following methods
The only way around this is to call your extension method using normal static method syntax. So instead of this:
e.HasFlag();
you would have to do this:
Extensions.HasFlag(e);
But if you add other parameters to your extension methods then it is not same to main methods, so when you call HasFlag method, the extension method called actually. For example:
public static bool HasFlag(this Enum e, bool isNullable)
{
return false;
}
References:
Extension Methods (C# Programming Guide)
Extension Methods, Nulls, Namespaces and Precedence in C#

Related

Which C# method overload is chosen?

Why is the generic method called when both overloads would match?
public static void method1(object obj)
{
Console.WriteLine("Object");
}
public static void method1<T>(T t)
{
Console.WriteLine("Type T");
}
public static void Main(String args[])
{
method1("xyz"); //Will print "Type T";
}
There should not be any conflicts here, right?
Overloads are resolved by choosing the most specific overload. In this case, method1<string>(string) is more specific than method1(object) so that is the overload chosen.
There are details in section 7.4.2 of the C# specification.
If you want to select a specific overload, you can do so by explicitly casting the parameters to the types that you want. The following will call the method1(object) overload instead of the generic one:
method1((object)"xyz");
There are cases where the compiler won't know which overload to select, for example:
void method2(string x, object y);
void method2(object x, string y);
method2("xyz", "abc");
In this case the compiler doesn't know which overload to pick, because neither overload is clearly better than the other (it doesn't know which string to implicitly downcast to object). So it will emit a compiler error.
C# will always choose the most specific method it can.
When compiling
method1("xyz");
it will look for all methods with the specified name and then attempt to match parameters. The compiler will choose the method that is the most specific, in this case it would prefer
method1(string s)
over
method1<T>(T t) with T = string
and lastly
method1(object o)
Please note #Erik's excellent answer for an example where the compiler fails to decide.
Because you are already passing in T as a parameter so you don't need to type out method1<string>("xyz");you can just go method1("xyz");, .Net already knows it's a string. If you had method1 then it would be a different story.
Also since method1(object obj) doesn't take in a string as parameter it will favor the generic function first where it can infer T. If you were to change method1(object obj) to method1(string obj) it would favor it first then the generic.
How method overloading works
To find the matching signature of a method for a call, the compiler search in the type hierarchy from bottom to top as well in virtual table:
First in the class hierarchy,
Then in the interface hierarchy.
Because classes prevail on interfaces.
Indeed, before being of type of an interface, an object is of type of a class first of all.
And non generic signatures prevail over generic as reality and facts prevail over abstraction, unless using the generic parameter allow a call on the more specialized type of instance.
Applying the theory to the question
This call:
method1("xyz");
Match perfectly with:
void method1<T>(T t) { }
Before matching with:
void method1(object obj)
Because string is a specialized object and it can be used as a generic parameter to be more acurate.
On the other side, if you write:
void method1(string obj) { }
void method1<T>(T t) { }
The first method is so called.
Case study
var instance = new List<string>();
MyMethod(instance);
MyMethod((IEnumerable<string>) instance);
MyMethod<string>(instance);
MyMethod((object)instance);
void MyMethod<T>(List<T> instance) { }
void MyMethod<T>(IEnumerable<T> list) { }
void MyMethod<T>(T instance) { }
void MyMethod(object instance) { }
The first call calls the first method because instance is type of List (type matching).
The second call calls the second method because of the side cast (implementation).
The third call calls the third method because of the generic parameter specified to act on (templating).
The fourth call calls the fourth method because of the down cast (polymorphism).

Extend "object" with a null check more readable than ReferenceEquals

I tried to extend "object" to allow a more readable check if an object is null.
Now, object.ReferenceEquals really checks for a null object, (the rare times it will not apply are since the operator == can be overridden. the object.Equals(null) method can also be overridden).
But the object.ReferenceEquals(null, obj); is not too readable is it?... So, I thought, why not write an extension method to the System.object that will provide that check using object.IsNull(obj);
I've tried:
public static class MyExtClass
{
// the "IsNull" extension to "object"
public static bool IsNull(this object obj)
{
return object.ReferenceEquals(obj, null);
}
}
public SomeOtherClass
{
public static void TryUsingTheExtension()
{
object obj;
// Why does this line fail? the extension method is not recognized
// I get: 'object' does not contain a definition for "IsNull"
bool itIsANull = object.IsNull(obj);
}
}
What did I miss?
Extension methods can be invoked only on instance and not on a class that they extend. So this line of code bool itIsANull = object.IsNull(obj); is incorrect because object is type and not an instance. Change it to :
bool itIsANull = (new object()).IsNull();
Or you can call it on class MyExtClass but not on object class (which is located in mscore.lib) :
MyExtClass.IsNull(new object());
P.S.
It looks like you missed something about extension methods. The truth is that they have nothing to do with classes that they extend. It's just a convenience that is provided for us by Intellisense with use of reflection.
Object class is located in mscorelib and is immutable. You can't add something to it. But what really happens is that Intellisense searches for all public methods that are located in public static classes and accept first argument with keyword 'this' as parameter. If one is found it's 'mapped' to the class that it extends. So when we type obj.MyExtMethod() on instance of that class it is automatically converted by compiler to Helper.MyExtMethod(obj); (if helper is our static class);
Try
bool itIsANull = obj.IsNull();
You wrote an extension method, and extension methods exist in a different type but extend objects of the specified type by another method.
But when you call object.IsNull(), then you are looking for a static method that exists on the object type.
Instead, you have two ways to call your method:
// either the static method on the class
MyExtClass.IsNull(obj);
// or using the actual feature of extension methods
obj.isNull();
Because it’s an extension method, the latter form will be automatically converted into the former at compile time.
You are calling the extension method on the object itself. You should call the methd on the instance instead -
bool itIsANull = obj.IsNull()
Try:
class Program
{
static void Main(string[] args)
{
var o = new object();
if (o.IsNull())
{
Console.Write("null");
}
}
}
public static class Request
{
public static bool IsNull(this object obj)
{
return ReferenceEquals(obj, null);
}
}
public static class MyExtClass
{
// the "IsNull" extension to "object"
public static bool IsNull(this object obj)
{
return object.ReferenceEquals(obj, null);
}
}
public class SomeOtherClass
{
public static void TryUsingTheExtension()
{
object obj =null;
bool itIsANull = obj.IsNull();
}
}

C#, an extension method to return a string list of named constants from any enum

I'm trying to make an extension method that can apply to all/any enum, that returns the string constants of the enum as a list of strings.
this did not work.
static class EnumEx
{
public static List<string> ToList(this System.Enum e)
{
return System.Enum.GetNames (e.GetType()).ToList();
}
}
I'm calling it like:
public enum TestEnum { HELLO, WORLD };
foreach(string e in TestEnum.ToList())
Console.Writeline(e);
UPDATE:
TestEnum instance = new TestEnum();
foreach(string e in instance.ToList())
Console.Writeline(e);
and get the errors:
Type string[]' does not contain a memberToList' and the best extension method overload EnumEx.ToList(this System.Enum)' has some invalid arguments
Extension method instance typestring[]' cannot be converted to `System.Enum'
When using extension methods, you need an instance on which to call that method. Using your method, you can do this:
var instance = new System.ConsoleModifiers();
Console.WriteLine(instance.ToList().Count());
If you want more information about why C# doesn't support static extension methods, you can read about that here: https://stackoverflow.com/a/4914207/573218

How to Extend the Type Class

this is my code:
bool ch=Type.IsBuiltIn("System.Int32"); // not working-> syntax error
public static class MyExtentions
{
public static bool IsBuiltIn(this Type t, string _type)
{
return (Type.GetType(_type) == null) ? false : true;
}
}
Please I want Extend Type Class by IsBuiltIn new method
You can't have static extension methods. Your extension method works on an instance of the Type class, so to call it you'd have to do something like this:
typeof(Type).IsBuiltIn("System.Int32")
The workaround for this is to just put your extension method in a utility class, e.g. like the following, and call it like a normal static function:
public static class TypeExt
{
public static bool IsBuiltIn(string _type)
{
return Type.GetType(_type) == null;
}
}
// To call it:
TypeExt.IsBuiltIn("System.Int32")
By the way, I don't think this will tell you whether the type is "built-in"; it will merely tell you whether a type with the given name has been loaded into the process.
Extension methods are intended to describe new APIs on instances, not types. In your case, that API would be something like:
Type someType = typeof(string); // for example
bool isBuiltIn = someType.IsBuiltIn("Some.Other.Type");
which... clearly isn't what you wanted; the type here adds nothing and is not related to the IsBuiltIn. There is no compiler trick for adding new static methods to existing types, basically - so you will not be able to use Type.IsBuiltIn("Some.Other.Type").
You can't extend the Type class. You need an instance of the class to create an extension method.
Edit:
See here and here.

Why is Static required here

If this question is too simple I apologize in advance.
Why does the method NthIndexOf found in the link below require a static class and also static class member?
C# - indexOf the nth occurrence of a string?
Because it is an extension method (MSDN) -- notice the keyword this before the first parameter.
This allows you to use the syntax:
var result = "foo bar".NthIndexOf("o", 1);
…as though you had added the NthIndexOf method to the System.String type. This would be available anywhere the namespace for that static class was available (using MyExtensions; for example).
Extension methods must be declared as static methods of public, non-nested static classes, but the same logic can be encapsulated without using an extension method, in which case there would be no requirement to use a static class & method.
Because it's an EXTENSION METHOD (EM).
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.
For example:
String is a .Net type. Prior to EM, without deriving, you cannot add your own method to string type. Even if you did so by deriving, that method would be counted as method of derived type and not of string type.
But now with EM's you can do so without deriving from it.
Requirements of EM (in C#)
They have to be public and static
The class in which they are defined is also public and static.
Most Important: First parameter should be that type for which you are creating your EM and should have this keyword in front of it. Without it, your method would not be an EM and would be a static method only.
In your earlier scenaro your EM NthIndexOf is defined in static class StringExtender
public static class StringExtender
{
public static int NthIndexOf(this string target, string value, int n)
{
....
}
}
Now since first parameter contains this in front of string so you can call it as
int result = "My string".NthIndexOf("M", 0);
If it was not EM and a plain static method like this
public static class StringExtender
{
public static int NthIndexOf(string target, string value, int n)
{
....
}
}
then it had to be called like
int result = NthIndexOf("My string", "M", 0);
It's an extension method which requires the static keyword.

Categories

Resources