I'm a fan of extension methods in C#, but haven't had any success adding an extension method to a static class, such as Console.
For example, if I want to add an extension to Console, called 'WriteBlueLine', so that I can go:
Console.WriteBlueLine("This text is blue");
I tried this by adding a local, public static method, with Console as a 'this' parameter... but no dice!
public static class Helpers {
public static void WriteBlueLine(this Console c, string text)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(text);
Console.ResetColor();
}
}
This didn't add a 'WriteBlueLine' method to Console... am I doing it wrong? Or asking for the impossible?
No. Extension methods require an instance variable (value) for an object. You can however, write a static wrapper around the ConfigurationManager interface. If you implement the wrapper, you don't need an extension method since you can just add the method directly.
public static class ConfigurationManagerWrapper
{
public static ConfigurationSection GetSection( string name )
{
return ConfigurationManager.GetSection( name );
}
.....
public static ConfigurationSection GetWidgetSection()
{
return GetSection( "widgets" );
}
}
Can you add static extensions to classes in C#? No but you can do this:
public static class Extensions
{
public static T Create<T>(this T #this)
where T : class, new()
{
return Utility<T>.Create();
}
}
public static class Utility<T>
where T : class, new()
{
static Utility()
{
Create = Expression.Lambda<Func<T>>(Expression.New(typeof(T).GetConstructor(Type.EmptyTypes))).Compile();
}
public static Func<T> Create { get; private set; }
}
Here's how it works. While you can't technically write static extension methods, instead this code exploits a loophole in extension methods. That loophole being that you can call extension methods on null objects without getting the null exception (unless you access anything via #this).
So here's how you would use this:
var ds1 = (null as DataSet).Create(); // as oppose to DataSet.Create()
// or
DataSet ds2 = null;
ds2 = ds2.Create();
// using some of the techniques above you could have this:
(null as Console).WriteBlueLine(...); // as oppose to Console.WriteBlueLine(...)
Now WHY did I pick calling the default constructor as an example, and AND why don't I just return new T() in the first code snippet without doing all of that Expression garbage?
Well todays your lucky day because you get a 2fer. As any advanced .NET developer knows, new T() is slow because it generates a call to System.Activator which uses reflection to get the default constructor before calling it. Damn you Microsoft!
However my code calls the default constructor of the object directly.
Static extensions would be better than this but desperate times call for desperate measures.
It's not possible.
And yes, I think MS made a mistake here.
Their decision does not make sense and forces programmers to write (as described above) a pointless wrapper class.
Here is a good example: Trying to extend static MS Unit testing class Assert: I want 1 more Assert method AreEqual(x1,x2).
The only way to do this is to point to different classes or write a wrapper around 100s of different Assert methods. Why!?
If the decision was being made to allow extensions of instances, I see no logical reason to not allow static extensions. The arguments about sectioning libraries does not stand up once instances can be extended.
I stumbled upon this thread while trying to find an answer to the same question the OP had. I didn't find the answer I wanted, but I ended up doing this.
public static class Helpers
{
public static void WriteLine(this ConsoleColor color, string text)
{
Console.ForegroundColor = color;
Console.WriteLine(text);
Console.ResetColor();
}
}
And I use it like this:
ConsoleColor.Cyan.WriteLine("voilà");
As of C#7 this isn't supported. There are however discussions about integrating something like that in C#8 and proposals worth supporting.
Maybe you could add a static class with your custom namespace and the same class name:
using CLRConsole = System.Console;
namespace ExtensionMethodsDemo
{
public static class Console
{
public static void WriteLine(string value)
{
CLRConsole.WriteLine(value);
}
public static void WriteBlueLine(string value)
{
System.ConsoleColor currentColor = CLRConsole.ForegroundColor;
CLRConsole.ForegroundColor = System.ConsoleColor.Blue;
CLRConsole.WriteLine(value);
CLRConsole.ForegroundColor = currentColor;
}
public static System.ConsoleKeyInfo ReadKey(bool intercept)
{
return CLRConsole.ReadKey(intercept);
}
}
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteBlueLine("This text is blue");
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
}
}
}
Nope. Extension method definitions require an instance of the type you're extending. It's unfortunate; I'm not sure why it's required...
You can't add static methods to a type. You can only add (pseudo-)instance methods to an instance of a type.
The point of the this modifier is to tell the C# compiler to pass the instance on the left-side of the . as the first parameter of the static/extension method.
In the case of adding static methods to a type, there is no instance to pass for the first parameter.
As for extension methods, extension methods themselves are static; but they are invoked as if they are instance methods. Since a static class is not instantiable, you would never have an instance of the class to invoke an extension method from. For this reason the compiler does not allow extension methods to be defined for static classes.
Mr. Obnoxious wrote: "As any advanced .NET developer knows, new T() is slow because it generates a call to System.Activator which uses reflection to get the default constructor before calling it".
New() is compiled to the IL "newobj" instruction if the type is known at compile time. Newobj takes a constructor for direct invocation. Calls to System.Activator.CreateInstance() compile to the IL "call" instruction to invoke System.Activator.CreateInstance(). New() when used against generic types will result in a call to System.Activator.CreateInstance(). The post by Mr. Obnoxious was unclear on this point... and well, obnoxious.
This code:
System.Collections.ArrayList _al = new System.Collections.ArrayList();
System.Collections.ArrayList _al2 = (System.Collections.ArrayList)System.Activator.CreateInstance(typeof(System.Collections.ArrayList));
produces this IL:
.locals init ([0] class [mscorlib]System.Collections.ArrayList _al,
[1] class [mscorlib]System.Collections.ArrayList _al2)
IL_0001: newobj instance void [mscorlib]System.Collections.ArrayList::.ctor()
IL_0006: stloc.0
IL_0007: ldtoken [mscorlib]System.Collections.ArrayList
IL_000c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0011: call object [mscorlib]System.Activator::CreateInstance(class [mscorlib]System.Type)
IL_0016: castclass [mscorlib]System.Collections.ArrayList
IL_001b: stloc.1
I tried to do this with System.Environment back when I was learning extension methods and was not successful. The reason is, as others mention, because extension methods require an instance of the class.
It is not possible to write an extension method, however it is possible to mimic the behaviour you are asking for.
using FooConsole = System.Console;
public static class Console
{
public static void WriteBlueLine(string text)
{
FooConsole.ForegroundColor = ConsoleColor.Blue;
FooConsole.WriteLine(text);
FooConsole.ResetColor();
}
}
This will allow you to call Console.WriteBlueLine(fooText) in other classes. If the other classes want access to the other static functions of Console, they will have to be explicitly referenced through their namespace.
You can always add all of the methods in to the replacement class if you want to have all of them in one place.
So you would have something like
using FooConsole = System.Console;
public static class Console
{
public static void WriteBlueLine(string text)
{
FooConsole.ForegroundColor = ConsoleColor.Blue;
FooConsole.WriteLine(text);
FooConsole.ResetColor();
}
public static void WriteLine(string text)
{
FooConsole.WriteLine(text);
}
...etc.
}
This would provide the kind of behaviour you are looking for.
*Note Console will have to be added through the namespace that you put it in.
The following was rejected as an edit to tvanfosson's answer. I was asked to contribute it as my own answer. I used his suggestion and finished the implementation of a ConfigurationManager wrapper. In principle I simply filled out the ... in tvanfosson's answer.
No. Extension methods require an instance of an object. You can
however, write a static wrapper around the ConfigurationManager
interface. If you implement the wrapper, you don't need an extension
method since you can just add the method directly.
public static class ConfigurationManagerWrapper
{
public static NameValueCollection AppSettings
{
get { return ConfigurationManager.AppSettings; }
}
public static ConnectionStringSettingsCollection ConnectionStrings
{
get { return ConfigurationManager.ConnectionStrings; }
}
public static object GetSection(string sectionName)
{
return ConfigurationManager.GetSection(sectionName);
}
public static Configuration OpenExeConfiguration(string exePath)
{
return ConfigurationManager.OpenExeConfiguration(exePath);
}
public static Configuration OpenMachineConfiguration()
{
return ConfigurationManager.OpenMachineConfiguration();
}
public static Configuration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap, ConfigurationUserLevel userLevel)
{
return ConfigurationManager.OpenMappedExeConfiguration(fileMap, userLevel);
}
public static Configuration OpenMappedMachineConfiguration(ConfigurationFileMap fileMap)
{
return ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
}
public static void RefreshSection(string sectionName)
{
ConfigurationManager.RefreshSection(sectionName);
}
}
yes, in a limited sense.
public class DataSet : System.Data.DataSet
{
public static void SpecialMethod() { }
}
This works but Console doesn't because it's static.
public static class Console
{
public static void WriteLine(String x)
{ System.Console.WriteLine(x); }
public static void WriteBlueLine(String x)
{
System.Console.ForegroundColor = ConsoleColor.Blue;
System.Console.Write(.x);
}
}
This works because as long as it's not on the same namespace. The problem is that you have to write a proxy static method for every method that System.Console have. It's not necessarily a bad thing as you can add something like this:
public static void WriteLine(String x)
{ System.Console.WriteLine(x.Replace("Fck","****")); }
or
public static void WriteLine(String x)
{
System.Console.ForegroundColor = ConsoleColor.Blue;
System.Console.WriteLine(x);
}
The way it works is that you hook something into the standard WriteLine. It could be a line count or bad word filter or whatever. Whenever you just specify Console in your namespace say WebProject1 and import the namespace System, WebProject1.Console will be chosen over System.Console as default for those classes in namespace WebProject1. So this code will turn all the Console.WriteLine calls into blue insofar as you never specified System.Console.WriteLine.
You can use a cast on null to make it work.
public static class YoutTypeExtensionExample
{
public static void Example()
{
((YourType)null).ExtensionMethod();
}
}
The extension:
public static class YourTypeExtension
{
public static void ExtensionMethod(this YourType x) { }
}
YourType:
public class YourType { }
Although the methods of Console are static, its static methods Write() and WriteLine() merely redirect the call to Console.Out.Write() and Console.Out.WriteLine() respectively. Out is an instance whose type derives from the abstract class TextWriter. This makes it possible to define extension methods for TextWriter:
public static class ConsoleTextWriterExtensions
{
public static void WriteBlueLine(this TextWriter writer, string text)
{
Console.ForegroundColor = ConsoleColor.Blue;
writer.WriteLine(text);
Console.ResetColor();
}
public static void WriteUppercase(this TextWriter writer, string text)
{
writer.Write(text.ToUpper());
}
}
The method can then be invoked like this:
Console.Out.WriteBlueLine();
And the best part is that the type of the standard error stream instance Console.Error also derives from TextWriter which makes the same extension method also usable for Console.Error:
Console.Error.WriteBlueLine();
This can be quite useful if you have defined an extension method like WriteTable()(for writing a table out to the console) because you can also use it for the error stream or any other object of TextWriter.
Newer versions of C# allow this to be even shorter with a using static statement for Console to get red of the Console. prefix:
using static System.Console;
Out.WriteBlueLine("A blue line");
Error.WriteBlueLine("A blue line");
unfotunately NO, you CANNOT extend static classes
https://onecompiler.com/csharp/3xvbe7axg
using System;
namespace HelloWorld
{
public static class console_extensions {
public static void EXTENSION(this object item) {
System.Console.WriteLine("HELLO THERE!");
}
}
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
Console.EXTENSION();
((Console)null).EXTENSION();
Console l = new Console();
l.EXTENSION();
}
}
}
output
Compilation failed: 4 error(s), 0 warnings
HelloWorld.cs(16,12): error CS0117: `System.Console' does not contain a definition for `EXTENSION'
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
HelloWorld.cs(17,5): error CS0716: Cannot convert to static type `System.Console'
HelloWorld.cs(18,4): error CS0723: `l': cannot declare variables of static types
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
HelloWorld.cs(18,16): error CS0712: Cannot create an instance of the static class `System.Console'
/usr/lib/mono/4.5/mscorlib.dll (Location of the symbol related to previous error)
however you CAN pass null to the extension method
using System;
namespace HelloWorld
{
public static class static_extensions {
public static void print(this object item, int data = 0) {
Console.WriteLine("EXT: I AM A STATIC EXTENSION!");
Console.WriteLine("EXT: MY ITEM IS: " + item);
Console.WriteLine("EXT: MY DATA IS: " + data);
string i;
if (item == null) {
i = "null";
} else {
i = item.GetType().Name;
}
Console.WriteLine("EXT: MY TYPE IS: " + i + "\n");
}
}
public class Program
{
public static void Main(string[] args)
{
// an extension method can be
// called directly
// (null is an instance)
static_extensions.print(null);
// an extension method can also be
// called directly with arguments
// (null is an instance)
static_extensions.print(null, 1);
// an extension method can also be
// called as part of an instance
int x = 0; // initialize int
x.print();
// an extension method can also be
// called as part of an instance
// and with data
int x2 = 0; // initialize int
x2.print(2);
// an extension method can also be
// called directly from null
// since `null` is an instance
((string)null).print();
// an extension method can also be
// called directly from null
// and with data
// since `null` is an instance
((string)null).print(4);
}
}
}
live example: https://onecompiler.com/csharp/3xvbc8s6w
output:
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS:
EXT: MY DATA IS: 0
EXT: MY TYPE IS: null
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS:
EXT: MY DATA IS: 1
EXT: MY TYPE IS: null
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 0
EXT: MY DATA IS: 0
EXT: MY TYPE IS: Int32
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS: 0
EXT: MY DATA IS: 2
EXT: MY TYPE IS: Int32
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS:
EXT: MY DATA IS: 0
EXT: MY TYPE IS: null
EXT: I AM A STATIC EXTENSION!
EXT: MY ITEM IS:
EXT: MY DATA IS: 4
EXT: MY TYPE IS: null
I don't really get what people think they'd gain from being able to extend static classes...
What exactly would you be sacrificing by simply doing something like this?
public static class MyConsole
{
public static void WriteBlueLine(string text)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(text);
Console.ResetColor();
}
}
//...
MyConsole.WriteBlueLine("I'm so blue...");
Console.WriteLine("...and I'm not.");
It's minimal extra typing effort and as a bonus, it keeps things transparent...
After all, even a regular extension method is just a shorthand for a helper method. It doesn't allow you to do anything to/with a class (instance) that you wouldn't be able to do from a regular method.
You CAN do this if you are willing to "frig" it a little by making a variable of the static class and assigning it to null. However, this method would not be available to static calls on the class, so not sure how much use it would be:
Console myConsole = null;
myConsole.WriteBlueLine("my blue line");
public static class Helpers {
public static void WriteBlueLine(this Console c, string text)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(text);
Console.ResetColor();
}
}
Related
This question already has answers here:
calling an overloaded method in generic method
(5 answers)
Closed 2 years ago.
In the code below I'm (wrongfully apparently) expecting that method of the more specific (derived if you will) type, to be bound/called:
using System;
public class Program
{
public static int integer = 52;
public static Program program = new Program();
public static void Main()
{
TestReturn(program); // this works as expected all the way
TestReturn(integer); // 1. this not quite...
}
public static T TestReturn<T>(T t) // 2. TestReturn<Int32> all good...
{
Console.WriteLine("In TestReturn<" + typeof(T) + ">");
return (T)Extensions.Undefined(t); // 3. wrong call
}
}
public static class Extensions
{
public static object Undefined(this object t) // 4. this is called, instead of (5)
{
Console.WriteLine("In Undefined(obj)");
return null;
}
public static int Undefined(this int b) // 5. this is expected to be called
{
Console.WriteLine("In Undefined(int)");
return int.MinValue;
}
}
Output:
In TestReturn<Program>
In Undefined(obj)
In TestReturn<System.Int32>
In Undefined(obj)
Run-time exception (line 17): Object reference not set to an instance of an object.
Can someone tell why is this happening and how to do it in order to work as I intended?
Taking from the C# Programming guide:
The basic definition of extension method says:
The intermediate language (IL) generated by the compiler translates your code into a call on the static method.
How the extension methods are binded at run time:
An extension method with the same name and signature as an interface or class method will never be called. At compile time, extension methods always have lower priority than instance methods defined in the type itself.
When the compiler encounters a method invocation, it first looks for a match in the type's instance methods. If no match is found, it will search for any extension methods that are defined for the type, and bind to the first extension method that it finds.
Extending predefined types can be difficult with struct types because they're passed by value to methods. That means any changes to the struct are made to a copy of the struct. Those changes aren't visible once the extension method exits.
As per documentation, and also mentioned in the comments by #UnholySheep and #Alexander Høst, at the compile time of your Program class, the compiler choses the more generic type to suffice the general approach of your "T" type. In other words, the extension method covering an "object" is chosen by the compiler as "T" might be anything.
The proof of concept it that the following code won't compile:
namespace ConsoleForEverything
{
public class Program
{
public static int integer = 52;
public static Program program = new Program();
public static void Main()
{
TestReturn(integer); // 1. this not quite...
}
public static T TestReturn<T>(T t) // 2. TestReturn<Int32> all good...
{
Console.WriteLine("In TestReturn<" + typeof(T) + ">");
return (T)Extensions.Undefined(t); // 3. wrong call
}
}
public static class Extensions
{
public static int Undefined(this int b) // 5. this is expected to be called
{
Console.WriteLine("In Undefined(int)");
return int.MinValue;
}
}
}
I understand that we could use the class name.method but I was wondering if there was a way to do it through an instance. Can you provide me an example also. The reason I'm asking is because my professor said:
You MUST invoke the extension method using calls that use the static
call form and the instance call form
With the edit that this is talking about extension methods, then it becomes easier!
With the same example as below:
bool hasValue1 = s.HasValue(); // use the instance syntax
bool hasValue2 = StringExtensions.HasValue(s); // use the static syntax
Note that these are 100% identical; once compiled to IL you cannot determine which form was used.
Short answer: "no", per CS0176:
CS0176 Member '{name}' cannot be accessed with an instance reference; qualify it with a type name instead
Slightly longer answer: if you really want to do that, maybe extension methods are what you are looking for; for example:
static class StringExtensions
{
public static bool HasValue(this string value)
{
return !string.IsNullOrEmpty(value);
}
}
class Program
{
static void Main()
{
string s = /* some string or null reference */
bool hasValue = s.HasValue();
}
}
This is a simple program I created - one table class, one main class. In the table class I created a print method which simply outputs my name. From the main class I am calling the print method but not getting the output.
namespace ConsoleApplication3
{
class table
{
public static void print()
{
Console.WriteLine("My name is prithvi-raj chouhan");
}
}
class Program
{
public static void Main()
{
table t = new table();
t.print(); // Error the program is not giving output while calling the print method
}
}
}
Since the function you are calling is static.
Use this syntax
public static void Main()
{
table.print();
}
Quote from MSDN:-
A static method, field, property, or event is callable on a class even
when no instance of the class has been created. If any instances of
the class are created, they cannot be used to access the static
member. Only one copy of static fields and events exists, and static
methods and properties can only access static fields and static
events. Static members are often used to represent data or
calculations that do not change in response to object state; for
instance, a math library might contain static methods for calculating
sine and cosine.
print is a static method, so call it as a static method:
public static void Main()
{
table.print();
}
try this:
class Program
{
public static void Main()
{
table.Print();
}
}
Print(); is a static method so you dont need to instantiate a new Table object in order to access it's methods
You are calling print() as an instance method but it is static. Try to remove the static keyword from the method.
Try to add a Console.ReadLine(); after table.print();.
UPDATE:
Missed the part with static, now corrected.
Going from Java to C# I have the following question:
In java I could do the following:
public class Application {
static int attribute;
static {
attribute = 5;
}
// ... rest of code
}
I know I can initialize this from the constructor but this does not fit my needs (I want to initialize and call some utility functions without create the object).
Does C# support this? If yes, how can I get this done?
Thanks in advance,
public class Application
{
static int attribute;
static Application()
{
attribute = 5;
} // removed
}
You can use the C# equivalent static constructors. Please don't confuse it with a regular constructor. A regular constructor doesn't have a static modifier in front of it.
I am assuming your //... rest of the code need to be also run once. If you don't have such code you can just simply do this.
public class Application
{
static int attribute = 5;
}
You just can write a static constructor block like this,
static Application(){
attribute=5;
}
This is what I could think of.
In your particular scenario, you could do the following:
public class Application {
static int attribute = 5;
// ... rest of code
}
UPDATE:
It sounds like you want to call a static method. You can do that as follows:
public static class Application {
static int attribute = 5;
public static int UtilityMethod(int x) {
return x + attribute;
}
}
I find something else useful. If your variable needs more than one expressions/statements to initialize, use this!
static A a = new Func<A>(() => {
// do it here
return new A();
})();
This approach is not limited on classes.
-A static constructor doesn't have any parameter.
-A static class can contain only one static constructor.
-A static constructor executes first when we run the program.
Example:
namespace InterviewPreparation
{
public static class Program
{ //static Class
static Program()
{ //Static constructor
Console.WriteLine("This is static consturctor.");
}
public static void Main()
{ //static main method
Console.WriteLine("This is main function.");
Console.ReadKey();
}
}
}
Output:
This is static constructor.
This is main function.
This is Visual Studio 2008. Obviously has to do with the static class for an extensions.
public class Dummy
{
public readonly int x;
public Dummy(int x)
{
this.x = x;
}
public override string ToString()
{
return x.ToString();
}
}
[Obsolete("Do Not Use", true)]
public static class Extensions
{
public static int Squared(this Dummy Dummy)
{
return Dummy.x * Dummy.x;
}
}
class Program
{
static void Main(string[] args)
{
var d = new Dummy(42);
Console.WriteLine(String.Format("{0}^2={1}", d, d.Squared()));
}
}
That repros in VS2010 as well. Looks like a bug. I'll get it entered in the database.
You can work around the bug by putting the attribute on the actual method.
Thanks for the report!
Calling an obsolete function is a warning, not an error, unless you change the compiler settings to stop on warnings too - to make warnings behave like errors.
Typically I don't see those warnings unless there are other 'real' errors in my code.
Also notice that in your specific case you marked the class as obsolete - not the method. That might matter.
I think You have found a compiler bug:
Although the extension method will be compiled to the static method usage, it seems the compiler does not check it since at the time of compilation it exists in the format of instance method call.
Reason is here. If I declare a second method:
[Obsolete("Do Not Use", true)]
public static class Extensions
{
public static int Squared(this Dummy Dummy)
{
return Dummy.x * Dummy.x;
}
public static int Squared2(Dummy Dummy)
{
return Dummy.x * Dummy.x;
}
}
Now it complains at the 3rd line not second:
class Program
{
static void Main(string[] args)
{
var d = new Dummy(42);
Console.WriteLine(String.Format("{0}^2={1}", d, d.Squared())); // Fine!?
Console.WriteLine(String.Format("{0}^2={1}", d, Extensions.Squared2(d))); // COmplains as expected
}
}
Because it's an extension method, you are not directly accessing the static class, the compiler generates that code.
If, instead, you accessed the Squared method explicitly, you would get the compile-time error.
Extensions.Squared(d)
Since this is an extension method, however, you only implicitly invoke the method, so the attribute will need to be applied to the method itself.
public static class Extensions
{
[Obsolete("Do Not Use", true)]
public static int Squared(this Dummy Dummy)
{
return Dummy.x * Dummy.x;
}
}
On the other hand, deleting (or renaming) the class altogether would serve the same purpose - you will definitely get a compile-time error in that case. :)
EDIT
You can file a bug report with Microsoft here. This seems like behavior that should be handled by the compiler.
I think you need to put the attribute on Squared, not the class.