Consider the following code:
1. namespace MyNS {
2. // A class
3. public class MyClass {
4. public string Do() {
5. return string.Blank();
6. }
7. // A nested type
8. protected static class Helper {
9. public static string Blank(this string str) {
10 return String.Empty;
11. }
12. }
13. }
14. } /* namespace */
However line 5 will cause the program not to compile. I know that in order to use extension methods a static class must be created and its enclosing namespace referenced through using directives.
How to achieve this when the static class is a nested class?
It cannot be done. Extensions methods cannot be defined in nested classes.
Although there is not major obstacle to implementing this feature, it does feel rather cumbersome: extension methods inside a nested class seem overkill as they might as well be defined as part of the outer class itself.
Also, it does force you to clearly organized this as extensions to your classes (again, is you must), rather a than part of them.
If you simply want to defined them locally (as in close to other related functionality), you might want to try SLaks' trick of creating the extensions methods inside a nested namespace declaration, making the class inside this new namespace not longer "nested".
You can't. For the method to be an extension method it needs to be in a non-nested class.
Related
I'm trying add the ability to lookup elements in a List<KeyValuePair<string,int>> by overriding the indexer.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
public class MyList : List<KeyValuePair<string, int>>
{
public int this[string key]
{
get
{
return base.Single(item => item.Key == key).Value;
}
}
}
}
For some reason, the compiler is throwing this error:
'System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string,int>>' does not contain a definition for 'Single'.
While it is true that List<T> doesn't have that method, it should be visible because it is an extension method from the System.Linq namespace (which is included). Obviously using this.Single resolves the issue, but why is access via base an error?
Section 7.6.8 of the C# spec says
When base.I occurs in a class or struct, I must denote a member of the base class of that class or struct.
Which might seem to preclude access to extension method via base. However it also says
At binding-time, base-access expressions of the form base.I and base[E] are evaluated exactly as if they were written ((B)this).I and ((B)this)[E], where B is the base class of the class or struct in which the construct occurs. Thus, base.I and base[E] correspond to this.I and this[E], except this is viewed as an instance of the base class.
If base.I is just like ((B)this).I then it seems like extension methods should be allowed here.
Can anyone explain the apparent contradiction in these two statements?
Consider this situation:
public class Base
{
public void BaseMethod()
{
}
}
public class Sub : Base
{
public void SubMethod()
{
}
}
public static class Extensions
{
public static void ExtensionMethod(this Base #base) { }
}
Here are some interesting assertions about this code:
I cannot call the extension method using ExtensionMethod() from neither Base nor Sub.
I cannot call base.ExtensionMethod() from Sub.
I can call the extension method using Extensions.ExtensionMethod(this) from both Sub and Base.
I can call the extension method using this.ExtensionMethod() from both Sub and Base.
Why is this?
I don't have a conclusive answer, partly because there might not be one: as you can read in this thread, you have to add this. if you want to call it in the extension method style.
When you're trying to use an extension method from the type it is in (or - consequently - from a type that is derived from the type used in the extension method), the compiler doesn't realize this and will try to call it as a static method without any arguments.
As the answer states: they [the language designers] felt it was not an important use case scenario to support implicit extension methods (to give the beast a name) from within the type because it would encourage extension methods that really should be instance methods and it was considered plain unnecessary.
Now, it is hard to find out what is happening exactly under the covers but from some playing around we can deduce that base.X() does not help us. I can only assume that base.X performs its virtual call as X() and not this.X() from the context of the baseclass.
What do I do when I want to call the extension method of a baseclass from a subclass?
Frankly, I haven't found any truly elegant solution. Consider this scenario:
public class Base
{
protected void BaseMethod()
{
this.ExtensionMethod();
}
}
public class Sub : Base
{
public void SubMethod()
{
// What comes here?
}
}
public static class Extensions
{
public static void ExtensionMethod(this Base #base)
{
Console.WriteLine ("base");
}
public static void ExtensionMethod(this Sub sub)
{
Console.WriteLine ("sub");
}
}
There are 3 ways (leaving aside reflection) to call the ExtensionMethod(Base) overload:
Calling BaseMethod() which forms a proxy between the subclass and the extensionmethod.
You can use BaseMethod(), base.BaseMethod() and this.BaseMethod() for this since now you're just dealing with a normal instance method which in its turn will invoke the extension method. This is a fairly okay solution since you're not polluting the public API but you also have to provide a separate method to do something that should have been accessible in the context in the first place.
Using the extension method as a static method
You can also use the primitive way of writing an extension method by skipping the syntactic sugar and going straight to what it will be compiled as. Now you can pass in a parameter so the compiler doesn't get all confused. Obviously we'll pass a casted version of the current instance so we're targetting the correct overload:
Extensions.ExtensionMethod((Base) this);
Use the - what should be identical translation - of base.ExtensionMethod()
This is inspired by #Mike z's remark about the language spec which says the following:
At binding-time, base-access expressions of the form base.I and base[E] are evaluated exactly as if they were written ((B)this).I and ((B)this)[E], where B is the base class of the class or struct in which the construct occurs. Thus, base.I and base[E] correspond to this.I and this[E], except this is viewed as an instance of the base class.
The spec literally says that base.I will be invoked as ((B) this).I. However in our situation, base.ExtensionMethod(); will throw a compilation error while ((Base) this).ExtensionMethod(); will work perfectly.
It looks like something is wrong either in the documentation or in the compiler but that conclusion should be drawn by someone with deeper knowledge in the matter (paging Dr. Lippert).
Isn't this confusing?
Yes, I would say it is. It kind of feels like a black hole within the C# spec: practically everything works flawlessly but then suddenly you have to jump through some hoops because the compiler doesn't know to inject the current instance in the method call in this scenario.
In fact, intellisense is confused about this situation as well:
We have already determined that that call can never work, yet intellisense believes it might. Also notice how it adds "using PortableClassLibrary" behind the name, indicating that a using directive will be added. This is impossible because the current namespace is in fact PortableClassLibrary. But of course when you actually add that method call:
and everything doesn't work as expected.
Perhaps a conclusion?
The main conclusion is simple: it would have been nice if this niche usage of extension methods would be supported. The main argument for not implementing it was because it would encourage people to write extension methods instead of instance methods.
The obvious problem here is of course that you might not always have access to the base class which makes extension methods a must but by the current implementation it is not possible.
Or, as we've seen, not possibly with the cute syntax.
Try to cast the instance to its base class:
((BaseClass)this).ExtensionMethod()
Applied to your code:
public class Base
{
public void BaseMethod()
{
}
}
public static class BaseExtensions
{
public static void ExtensionMethod(this Base baseObj) { }
}
public class Sub : Base
{
public void SubMethod()
{
( (Base) this).ExtensionMethod();
}
}
How can I access functions from a class without having to name that class every time? I know how to use "using" so that I don't have to name the namespace but I was hoping there was a way to do with this static functions so that I can call them the way I would call a function in the same class.
using static yournamespace.yourclassname;
then call the static class method without class name;
Example:
Class1.cs
namespace WindowsFormsApplication1
{
class Utils
{
public static void Hello()
{
System.Diagnostics.Debug.WriteLine("Hello world!");
}
}
}
Form1.cs
using System.Windows.Forms;
using static WindowsFormsApplication1.Utils;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Hello(); // <====== LOOK HERE
}
}
}
I routinely have
static Action<object> o = s => Console.WriteLine(s);
in my code which makes debug output so much less noisy. That way I can call Console's static Writeline() much easier. Would that help?
If you're looking to define a globally-scoped procedure then the short answer is no, you can't do this in c#. No global functions, procedures or objects.
In C# everything apart from namespaces and types (class, struct, enum, interface) must be defined inside a type. Static members (fields, properties and methods) can be used without an instance of the class, but only by referencing the type that owns them. Non-static members need an instance of the owning class.
This is fundamental to the syntax of the language. C# is neither C nor C++, where you can define global objects, functions and procedures.
In C#? Not possible. Because it's a full OOP programming language and it was designed to work with objects you can't use functions outside the scope of an object. When calling static methods you have to specify the class where that static method lives...
Class.StaticMethod();
you can only use the short-hand notation if this method is call from within the same class...
StaticMethod();
But remember that you will not get access to instance members because static methods donot belong to instance of an object
Update based on comment
Looks like it will be possible to call static members without having to specify the class that declares it in C# 6, and you will be able to reference classes directly in using statements...in similar fashion to Java...more info here
I found a class that looks something like:
using System;
// no using statement that brings either IMyClass or
// MyClassExtensions into scope
namespace Org.Foo {
class MyClass {
public void QuizzicalMethod(IMyClass thingy,
string stringToPass) {
thingy.ExtensionMethod(StringToPass);
}
}
There is an IMyClass interface definition in IMyClass.cs in the codebase (in the same namespace and directory), but it contains no definition for QuizzicalMethod. Instead, MyClassExtensions.cs has:
using System;
namespace Org.Foo {
public static class MyClassExtensions {
public static void ExtensionMethod (this IMyClass self,
string stringToPass) {
// Do some stuff
}
}
}
Thus, MyClassExtensions is clearly out of scope when MyClass is defined, and thus when QuizzicalMethod--which uses IMyClassExtensions.ExtensionMethod--is defined. It seems to me like both the parameter list of the QuizzicalMethod definition and its call of thingy.ExtensionMethod ought to break. (Makes me wonder if there's a code coverage issue in the tests.) This leads to some questions:
How does this compile without an error?
Why would a class author even want to bring QuizzicalMethod out of the class definition and put it into an extension?
Does this fit an existing named pattern?
Is there some kind of scoping exception or late-binding going on? If so, how does it not break everything else in C#?
Thanks in advance!
EDIT: Fixed some typos.
Thus, MyClassExtensions is clearly out of scope when MyClass is defined
Nope, both MyClassExtensions and MyClass are declared in the same namespace. You don't need a using directive to invoke an extension method in the same namespace or an enclosing namespace.
You haven't explained where IMyClass is declared, so I can't comment on that.
From section 7.6.5.2 of the C# 5 specification (talking about finding a class C containing an extension method):
The search for C proceeds as follows:
Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods:
If the given namespace or compilation unit directly contains non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.
If namespaces imported by using namespace directives in the given namespace or compilation unit directly contain non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.
Basically, this is just an extension method. Without knowing more of the real context, we can't comment on why this is an extension method rather than a method on IMyClass.
How does this compile without an error?
This compiles because the two classes are in the same namespace.
Why would a class author even want to bring QuizzicalMethod out of the class definition and put it into an extension?
It could have been done for backward compatibility: the author may wanted to publish this method as an extension when the class was already in production, without an ability to recompile classes that rely on MyClass.QuizzicalMethod.
It may have been done the other way around: it is the designer of MyClass who wanted to bring in the extension method into his class - for example, to make it easier for himself to access the method through reflection as an instance method (although it is certainly not a requirement - one can call an extension through reflection by calling a static method of the extension class).
Does this fit an existing named pattern?
Not as far as I know
Is there some kind of scoping exception or late-binding going on? If so, how does it not break everything else in C#?
Nothing special is going on here: two classes in the same namespace can see each other methods.
I have:
Main Program Class - uses Library A
Library A - has partial classes which mix in methods from Library B
Library B - mix in methods & interfaces
Why would I need a using statement to LibaryB just to get their extension methods working in the main class? That is given that it's Library B that defines the classes that will be extended.
EDIT - Except from code
// *** PROGRAM ***
using TopologyDAL;
using Topology; // *** THIS WAS NEEDED TO GET EXTN METHODS APPEARING ***
class Program
{
static void Main(string[] args)
{
var context = new Model1Container();
Node myNode; // ** trying to get myNode mixin methods to appear seems to need using line to point to Library B ***
}
}
// ** LIBRARY A
namespace TopologyDAL
{
public partial class Node
{
// Auto generated from EF
}
public partial class Node : INode<int> // to add extension methods from Library B
{
public int Key
}
}
// ** LIBRARY B
namespace ToplogyLibrary
{
public static class NodeExtns
{
public static void FromNodeMixin<T>(this INode<T> node) {
// XXXX
}
}
public interface INode<T>
{
// Properties
T Key { get; }
// Methods
}
}
Extension methods are only available if you import the namespace that they are defined in.
Otherwise, the compiler would need to resolve against every single extension method in every single referenced library, which would slow down the compile time.
Also, that would make it impossible to use an extension method if a different namespace contains an extension method with the same signature.
In summary, extension methods are features in their own right and require their namespace to be imported; they are not automatically imported with the namespace of the class that they extend.
This is an unfortunate discoverability issue with extension methods. In order to make them available you need to add a using statement for the namespace containing the static class that has the extensions. Check out this blog about extension methods.
Here is some background on extension methods:
So how is the compiler to know which
extension method to bind? The compiler
looks for extension methods in the
innermost namespace when the call is
made for extension methods and then in
all the namespaces imported by the
"using" clause. This process is
followed moving outward until we reach
the topmost namespace.
Since extension methods can be
imported in to the current context by
the "using" clause and bound to any
object which is assignable(see
convertibility section for details) to
the instance parameter, all sorts of
interesting possibilities open up for
extending the methods implemented by a
type. This can simply be done by
importing a library of extension
methods and using these methods as if
they were declared on a type that you
don't own. This means that
Depending on the library you import the code can be made to do different
things.
The client gets an interesting way to extend a type that he does not own.
My understanding is that using extension methods is just like using any other type, except that you can't qualify them (that is just syntactically impossible), hence the need for using statement. Since you can define multiple of them in different classes in different namespaces, the compiler needs a way to resolve ambiguity.
I envisage that in future Visual Studio will add a feature to import the right namespace when you type in the method name, in a similar way it does so for class and interface names.
Consider this scenario:
namespace FruityNamespace {
public static class FruityExtensions {
public static string ToFunString(this int value) {return value + " bananas"; }
}
}
namespace VegetablNamespace {
public static class VegetablyExtensions {
public static string ToFunString(this int value) {return value + " carrots"; }
}
}
//In some other source file
static void Main(/**/) {
int things = 3;
3.ToFunString(); //error CS1061: 'System.Int' does not contain a definition for 'ToFunString' and no extension method 'ToFunString' accepting a first argument of type 'System.Int' could be found (are you missing a using directive or an assembly reference?)
}
In order to use any of those extension methods you need to import the right namespace:
using FruityNamespace;
//OR
using VegetablyNamespace;
You might ask what happens when you import both namespaces. You get a compiler error just like this:
error CS0121: The call is ambiguous between the following methods or properties: 'VegetablNamespace.VegetablyExtensions.ToFunString(int)' and 'FruityNamespace.FruityExtensions.ToFunString(int)'
The only difference I see is the fact that you can't use the "using staticClass" declaration.
Therefore, I'm wondering:
Is there a real difference between a static class and a namespace?
Is there a possibility to avoid having to rewrite the class name every time a member function is called? I'm thinking about something analogous to "using staticClass".
Yes, a static class is technically a type. It can have members (fields, methods, events). A namespace can only hold types (and it's not considered a "type" by itself; typeof(System) is a compile-time error).
There's no direct equivalent to adding a using directive for a namespace for a static class. You can, however, declare aliases:
using ShortName = ReallyReallyLongStaticClassName;
and use
ShortName.Member
when referring its members.
Additionally, you can use static classes to declare extension methods on other types and use them directly without referring to the class name explicitly:
public static class IntExtensions {
public static int Square(this int i) { return i * i; }
}
and use it like:
int i = 2;
int iSquared = i.Square(); // note that the class name is not mentioned here.
Of course, you'll have to add a using directive for the namespace containing the class to use the extension method if the class is not declared in the root or current namespace.
Static class is still a class. It can contain methods, properties, etc. Namespace is just a namespace. It's just a helper to distinguish between class declarations with the same name.
Function can't live in a namespace alone, it belongs to a class.
Extensions is probably what you are looking for, if you need a static function without mentioning the name of the class.
public static class MathExtensions
{
public static int Square(this int x)
{
return x * x;
}
}
//...
// var hundredSquare = 100.Square();
One other difference is that namespaces can span several assemblies, while classes cannot.
As far as I understand, namespaces are a language feature only; they get removed by compilation. In other words, the .NET runtime does not "see" namespaces, just class names that happen to contain dots. For example, the String class in the System namespace is seen by the .NET runtime as a class named System.String, but there is no concept of namespace at all.
Static classes, however, are fully understood and managed by the .NET runtime. They are fully-fledged types and you can use reflection on them.