Static/Instance methods and extension questions - c#

I'm new to C# and I began working on a project that needed a method added to a class in C#. I found myself re examining the differences between static and instance methods and I'm unable to explain the following in a sample project.
My Core object:
namespace ExtendingObjects
{
public class MyCoreObject
{
public String name;
public String returnName()
{
return name;
}
}
}
My attempt to extend the object:
namespace ExtendingObjects
{
public static class Extensions
{
public static void addName(this MyCoreObject mco, String str)
{
mco.name=str;
}
public static String getName(this MyCoreObject mco)
{
return "test";
}
}
}
Calling program:
namespace ExtendingObjects
{
class Program
{
static void Main(string[] args)
{
MyCoreObject co = new MyCoreObject();
co.addName("test");
//Static method seems to work with instance?
String n = co.returnName();
Console.WriteLine("The name is " + n);
Console.ReadLine();
//Does not work
//Static method from a type
//String n2 = MyCoreObject.getName()
}
}
}
It was my understanding that static items stayed with the class and instance items with the instance per MSDN Static and Instance Members. However, I seem to be able to access a static method through an instance above, but not able to access a static method through a type.
Why does co.returnName() work and not MyCoreObject.getName()? I would think they would be reverse based on my reading. How can I make the getName() method available without instantiating the object first?
Thanks in advance.

Your two methods are extension methods, which are meant to look like instance methods when they're called. They can be called statically, but you need to supply the instance as the first argument, and specify the class which declares the extension method, not the type that the method "extends":
Extensions.getName(co);
When you call an extension method "as" an instance method, it's just a compiler trick. So this code:
co.addName("test");
is compiled to the exact equivalent of:
Extensions.addName(co, "test");
(As an aside, you would do well to start following normal .NET naming conventions as soon as possible. The earlier you get in the habit, the better.)

Related

"Member cannot be accessed with an instance reference; qualify it with a type name instead" [duplicate]

I am getting into C# and I am having this issue:
namespace MyDataLayer
{
namespace Section1
{
public class MyClass
{
public class MyItem
{
public static string Property1{ get; set; }
}
public static MyItem GetItem()
{
MyItem theItem = new MyItem();
theItem.Property1 = "MyValue";
return theItem;
}
}
}
}
I have this code on a UserControl:
using MyDataLayer.Section1;
public class MyClass
{
protected void MyMethod
{
MyClass.MyItem oItem = new MyClass.MyItem();
oItem = MyClass.GetItem();
someLiteral.Text = oItem.Property1;
}
}
Everything works fine, except when I go to access Property1. The intellisense only gives me "Equals, GetHashCode, GetType, and ToString" as options. When I mouse over the oItem.Property1, Visual Studio gives me this explanation:
MemberMyDataLayer.Section1.MyClass.MyItem.Property1.getcannot be accessed with an instance reference, qualify it with a type name instead
I am unsure of what this means, I did some googling but wasn't able to figure it out.
In C#, unlike VB.NET and Java, you can't access static members with instance syntax. You should do:
MyClass.MyItem.Property1
to refer to that property or remove the static modifier from Property1 (which is what you probably want to do). For a conceptual idea about what static is, see my other answer.
You can only access static members using the name of the type.
Therefore, you need to either write,
MyClass.MyItem.Property1
Or (this is probably what you need to do) make Property1 an instance property by removing the static keyword from its definition.
Static properties are shared between all instances of their class, so that they only have one value. The way it's defined now, there is no point in making any instances of your MyItem class.
I had the same issue - although a few years later, some may find a few pointers helpful:
Do not use ‘static’ gratuitously!
Understand what ‘static’ implies in terms of both run-time and compile time semantics (behavior) and syntax.
A static entity will be automatically constructed some time before
its first use.
A static entity has one storage location allocated, and that is
shared by all who access that entity.
A static entity can only be accessed through its type name, not
through an instance of that type.
A static method does not have an implicit ‘this’ argument, as does an
instance method. (And therefore a static method has less execution
overhead – one reason to use them.)
Think about thread safety when using static entities.
Some details on static in MSDN:
Static Classes in C#
Static Constructors in C#
This causes the error:
MyClass aCoolObj = new MyClass();
aCoolObj.MyCoolStaticMethod();
This is the fix:
MyClass.MyCoolStaticMethod();
Explanation:
You can't call a static method from an instance of an object. The whole point of static methods is to not be tied to instances of objects, but instead to persist through all instances of that object, and/or to be used without any instances of the object.
No need to use static in this case as thoroughly explained. You might as well initialise your property without GetItem() method, example of both below:
namespace MyNamespace
{
using System;
public class MyType
{
public string MyProperty { get; set; } = new string();
public static string MyStatic { get; set; } = "I'm static";
}
}
Consuming:
using MyType;
public class Somewhere
{
public void Consuming(){
// through instance of your type
var myObject = new MyType();
var alpha = myObject.MyProperty;
// through your type
var beta = MyType.MyStatic;
}
}
cannot be accessed with an instance reference
It means you're calling a STATIC method and passing it an instance. The easiest solution is to remove Static, eg:
public static void ExportToExcel(IEnumerable data, string sheetName)
{
Remove the static in the function you are trying to call. This fixed the problem for me.
I got here googling for C# compiler error CS0176, through (duplicate) question Static member instance reference issue.
In my case, the error happened because I had a static method and an extension method with the same name. For that, see Static method and extension method with same name.
[May be this should have been a comment. Sorry that I don't have enough reputation yet.]
I know this is an old thread, but I just spent 3 hours trying to figure out what my issue was. I ordinarily know what this error means, but you can run into this in a more subtle way as well. My issue was my client class (the one calling a static method from an instance class) had a property of a different type but named the same as the static method. The error reported by the compiler was the same as reported here, but the issue was basically name collision.
For anyone else getting this error and none of the above helps, try fully qualifying your instance class with the namespace name. ..() so the compiler can see the exact name you mean.
Check whether your code contains a namespace which the right most part matches your static class name.
Given the a static Bar class, defined on namespace Foo, implementing a method Jump or a property, chances are you are receiving compiler error because there is also another namespace ending on Bar. Yep, fishi stuff ;-)
If that's so, it means your using a Using Bar; and a Bar.Jump() call, therefore one of the following solutions should fit your needs:
Fully qualify static class name with according namepace, which result on Foo.Bar.Jump() declaration. You will also need to remove Using Bar; statement
Rename namespace Bar by a diffente name.
In my case, the foollowing compiler error occurred on a EF (Entity Framework) repository project on an Database.SetInitializer() call:
Member 'Database.SetInitializer<MyDatabaseContext>(IDatabaseInitializer<MyDatabaseContext>)' cannot be accessed with an instance reference; qualify it with a type name instead MyProject.ORM
This error arouse when I added a MyProject.ORM.Database namespace, which sufix (Database), as you might noticed, matches Database.SetInitializer class name.
In this, since I have no control on EF's Database static class and I would also like to preserve my custom namespace, I decided fully qualify EF's Database static class with its namepace System.Data.Entity, which resulted on using the following command, which compilation succeed:
System.Data.Entity.Database.SetInitializer<MyDatabaseContext>(MyMigrationStrategy)
Hope it helps
YourClassName.YourStaticFieldName
For your static field would look like:
public class StaticExample
{
public static double Pi = 3.14;
}
From another class, you can access the staic field as follows:
class Program
{
static void Main(string[] args)
{
double radius = 6;
double areaOfCircle = 0;
areaOfCircle = StaticExample.Pi * radius * radius;
Console.WriteLine("Area = "+areaOfCircle);
Console.ReadKey();
}
}

c# cannot access class because of protection level

hey guys I'm new to C# and I was practicing classes and methods and that stuff and I did the following code:
using System;
namespace ConsoleApp6
{
class Book
{
static void Review()
{
int x = 10;
Console.WriteLine(x);
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Book.Review);
}
}
}
It's really simple but when i ran it in said that it can't access the "Review" method because of it's protection level, please help
The reason for this error is that the default access modifier for methods is private, which means that only members of the same class can see them.
Since you want to reference the method from another class in the same namespace, you need to give broader access to the method by changing the access modifier to either internal (which means any classes in the same assembly can see it) or public (which means it can be seen by everybody).
Either one of these should solve your problem:
// Only members of the same assembly can access this method
internal static void Review() { // code omitted }
// Everyone can access this method
public static void Review() { // code omitted }
You can read more about access modifiers here.
Additionally, you have set the return value of Review to void, and are then trying to pass this to the Console.WriteLine() method, which expects an actual type. This will result in a compile error (something like: "cannot convert void to [someType]").
In order to solve this you could either just call the method from main and let the method write to the console:
private static void Main(string[] args)
{
Book.Review();
}
Or, my preference would be to have the method return a string, and then write that to the console in the Main method (I prefer this because it makes the method more versatile - someone could call it to simply retrieve a review without displaying it to the console, for example):
public static string Review()
{
int x = 10;
return x.ToString();
}
Note that when you call the method, you will need to include the parenthesis after the name:
private static void Main(string[] args)
{
Console.WriteLine(Book.Review());
}

c# cannot declare static and non static methods with same parameters?

If I try to declare static and non-static methods with the same parameters compiler returns an error: type 'Test' already defines a member called 'Load' with the same parameter types.
class Test
{
int i = 0;
public int I
{
get { return i; }
set { i = value; }
}
public bool Load(int newValue)
{
i = newValue;
return true;
}
public static Test Load(int newValue)
{
Test t = new Test();
t.I = newValue;
return t;
}
As far as I know these two methods can not be mixed, non static method is called on object whereas static method is called on class, so why does compiler not allow something like this and is there a way to do something similar?
If your Test class had a method like this:
public void CallLoad()
{
Load(5);
}
the compiler would not know which Load() to use. Calling a static method without the class name is entirely allowed for class members.
As for how to do something similar, I guess your best bet is to give the methods similar but different names, such as renaming the static method to LoadTest() or LoadItem().
Inside the class itself, you call both instance methods and static methods without an instance or the class name, thus making the two undistinguishable if the names and parameters are the same:
class Test
{
public void Foo()
{
Load(0); // Are you trying to call the static or the instance method?
}
// ...
}
The signature of a method is the combination of name and parameters (number and types).
In your case, your 2 methods have the same identical signature. The fact that one is static and other one is not makes no difference in accepting them as valid methods for the class.
I don't think so. if a non static method in this class calls Load(intValue). which method will be called?
Both methods have the same name, defined in the same class (scope) and with the same signature. C# does not allow this.
The problem is not related with writing this or the classname. C# specs allow you to call static methods using object instances:
AClass objectA = new AClass();
objectA.CallStaticMethod();
This code is valid so the compiler never has a way to know if you're calling a static or an instance method.
In C# a method cannot be overloaded by return type. It must at least have a different set of parameters, regardless if the method is static or not.

Member '<member name>' cannot be accessed with an instance reference

I am getting into C# and I am having this issue:
namespace MyDataLayer
{
namespace Section1
{
public class MyClass
{
public class MyItem
{
public static string Property1{ get; set; }
}
public static MyItem GetItem()
{
MyItem theItem = new MyItem();
theItem.Property1 = "MyValue";
return theItem;
}
}
}
}
I have this code on a UserControl:
using MyDataLayer.Section1;
public class MyClass
{
protected void MyMethod
{
MyClass.MyItem oItem = new MyClass.MyItem();
oItem = MyClass.GetItem();
someLiteral.Text = oItem.Property1;
}
}
Everything works fine, except when I go to access Property1. The intellisense only gives me "Equals, GetHashCode, GetType, and ToString" as options. When I mouse over the oItem.Property1, Visual Studio gives me this explanation:
MemberMyDataLayer.Section1.MyClass.MyItem.Property1.getcannot be accessed with an instance reference, qualify it with a type name instead
I am unsure of what this means, I did some googling but wasn't able to figure it out.
In C#, unlike VB.NET and Java, you can't access static members with instance syntax. You should do:
MyClass.MyItem.Property1
to refer to that property or remove the static modifier from Property1 (which is what you probably want to do). For a conceptual idea about what static is, see my other answer.
You can only access static members using the name of the type.
Therefore, you need to either write,
MyClass.MyItem.Property1
Or (this is probably what you need to do) make Property1 an instance property by removing the static keyword from its definition.
Static properties are shared between all instances of their class, so that they only have one value. The way it's defined now, there is no point in making any instances of your MyItem class.
I had the same issue - although a few years later, some may find a few pointers helpful:
Do not use ‘static’ gratuitously!
Understand what ‘static’ implies in terms of both run-time and compile time semantics (behavior) and syntax.
A static entity will be automatically constructed some time before
its first use.
A static entity has one storage location allocated, and that is
shared by all who access that entity.
A static entity can only be accessed through its type name, not
through an instance of that type.
A static method does not have an implicit ‘this’ argument, as does an
instance method. (And therefore a static method has less execution
overhead – one reason to use them.)
Think about thread safety when using static entities.
Some details on static in MSDN:
Static Classes in C#
Static Constructors in C#
This causes the error:
MyClass aCoolObj = new MyClass();
aCoolObj.MyCoolStaticMethod();
This is the fix:
MyClass.MyCoolStaticMethod();
Explanation:
You can't call a static method from an instance of an object. The whole point of static methods is to not be tied to instances of objects, but instead to persist through all instances of that object, and/or to be used without any instances of the object.
No need to use static in this case as thoroughly explained. You might as well initialise your property without GetItem() method, example of both below:
namespace MyNamespace
{
using System;
public class MyType
{
public string MyProperty { get; set; } = new string();
public static string MyStatic { get; set; } = "I'm static";
}
}
Consuming:
using MyType;
public class Somewhere
{
public void Consuming(){
// through instance of your type
var myObject = new MyType();
var alpha = myObject.MyProperty;
// through your type
var beta = MyType.MyStatic;
}
}
cannot be accessed with an instance reference
It means you're calling a STATIC method and passing it an instance. The easiest solution is to remove Static, eg:
public static void ExportToExcel(IEnumerable data, string sheetName)
{
Remove the static in the function you are trying to call. This fixed the problem for me.
I got here googling for C# compiler error CS0176, through (duplicate) question Static member instance reference issue.
In my case, the error happened because I had a static method and an extension method with the same name. For that, see Static method and extension method with same name.
[May be this should have been a comment. Sorry that I don't have enough reputation yet.]
I know this is an old thread, but I just spent 3 hours trying to figure out what my issue was. I ordinarily know what this error means, but you can run into this in a more subtle way as well. My issue was my client class (the one calling a static method from an instance class) had a property of a different type but named the same as the static method. The error reported by the compiler was the same as reported here, but the issue was basically name collision.
For anyone else getting this error and none of the above helps, try fully qualifying your instance class with the namespace name. ..() so the compiler can see the exact name you mean.
Check whether your code contains a namespace which the right most part matches your static class name.
Given the a static Bar class, defined on namespace Foo, implementing a method Jump or a property, chances are you are receiving compiler error because there is also another namespace ending on Bar. Yep, fishi stuff ;-)
If that's so, it means your using a Using Bar; and a Bar.Jump() call, therefore one of the following solutions should fit your needs:
Fully qualify static class name with according namepace, which result on Foo.Bar.Jump() declaration. You will also need to remove Using Bar; statement
Rename namespace Bar by a diffente name.
In my case, the foollowing compiler error occurred on a EF (Entity Framework) repository project on an Database.SetInitializer() call:
Member 'Database.SetInitializer<MyDatabaseContext>(IDatabaseInitializer<MyDatabaseContext>)' cannot be accessed with an instance reference; qualify it with a type name instead MyProject.ORM
This error arouse when I added a MyProject.ORM.Database namespace, which sufix (Database), as you might noticed, matches Database.SetInitializer class name.
In this, since I have no control on EF's Database static class and I would also like to preserve my custom namespace, I decided fully qualify EF's Database static class with its namepace System.Data.Entity, which resulted on using the following command, which compilation succeed:
System.Data.Entity.Database.SetInitializer<MyDatabaseContext>(MyMigrationStrategy)
Hope it helps
YourClassName.YourStaticFieldName
For your static field would look like:
public class StaticExample
{
public static double Pi = 3.14;
}
From another class, you can access the staic field as follows:
class Program
{
static void Main(string[] args)
{
double radius = 6;
double areaOfCircle = 0;
areaOfCircle = StaticExample.Pi * radius * radius;
Console.WriteLine("Area = "+areaOfCircle);
Console.ReadKey();
}
}

Can I add extension methods to an existing static class?

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();
}
}

Categories

Resources