Where's the # in C#?
I'm one of the lucky ones to go from Delphi to C#.
Lucky, because the two languages share their intellectual father, Anders Hejlsberg, who copied many existing Delphi and C++ language concepts to C#
This means that Delphi programmers have a big advantage to Visual Basic programmers because they're already familiar with inheritance, polymorphism. Even to C++ coders who lack interfaces, events and delegates, and a even proper IDE (except for the very underrated Borland C++ Builder maybe).
I know that c++ got it's name from the incremental operator (c++ as a next iteration of C), but where did C# get it's pound suffix from?
Still I'm disappointed to miss some features that are available in Delphi, but not implemented in C#, like:
Delegate by Interface
In delphi it's possible to delegate the complete implementation of an Interface to a property. This way you don't have to redeclare each interface member inside the class, but it is possible to pass it to functions that need a IMyInterface Implemenation:
IMyInterface = interface (IInterface) function Foo() : Boolean; procedure Bar(); end;
TMyInterfaceImpl = class ( IMyInterface ) function Foo : Boolean; procedure Bar() ; end;
TMyType = class ( TObject, IMyInterface ) private FMyImplementation : IMyInterface; protected function GetImplementation() : IMyInterface; public property MyImplementation : IMyInterface read GetImplementation implements IMyInterface; end; function TMyType.GetImplementation() begin if not assigned (FMyImplementation then FMyImplementation := TMyInterfaceImpl.Create(); result := FMyImplementation; end;
Currently in C# you have to redeclare each member and delegate it to the implementation if you want separate your interface implementation from the class :
public interface IMyInterface { bool Foo(); void Bar(); } public class MyInterfaceImpl : IMyInterface { bool IMyInterface.Foo(){ ... } void IMyInterface.Bar(){ ... } } public class MyType : IMyInterface { IMyInterface myImplementation; IMyInterface MyImplementation{ get { if (myImplementation==null) myImplementation = new MyInterfaceImpl(); return myImplementation; } } // All members have to be redeclared even though // the implementation is delegated to the // MyImplementation property bool IMyInterface.Foo(){ return MyImplementation.Foo(); } void IMyInterface.Bar(){ MyImplementation.Bar(); } }
Strictly Typed Types
In Delphi it's possible to declare a variable, that contains a reference to the class of a type, and can be used as a type. I know that sounds a little complex (don't even know if it's correct) but an example should clarify:
TMyType = class ( TObject, IMyInterface ) private FMyImplementation : IMyInterface; protected function GetImplementation() : IMyInterface; public property MyImplementation : IMyInterface read GetImplementation implements IMyInterface; end; TMyTypeClass = class of TMyType; function CreateInstance(AType : TMyTypeClass):TMyType begin result := AType.Create(); end; procedure Main() var MyType : TMyType; begin MyType := CreateInstance(TMyType); end;
Now it's only possible to pass a type that inherits from TMyType.
Why doesn't c# have anything like this? C# only knows the Type type, and if you would want a method to only accept a certain type, you need to do it like this:
public MyType CreateInstance(Type type){ if( !type.IsSubclassOf( typeof(MyType) ) ) throw new ArgumentException("Type parameter is of incorrect type"); return Activator.CreateInstance(type); } public static void Main(){ MyType instance = CreateInstance(typeof(MyType)); }
Type Suffices and Generics in C# 2.0:
With generics in C# 2.0 it's possible achieve something like strictly typed types, using the where keyword in generics, wich will force the collection to only accept members that implement ICloneable:
public class CloneableCollection<T> : Collection<T>, ICloneable where T : ICloneable { public CloneableCollection<T> Clone() { CloneableCollection<T> collection = new CloneableCollection<T>(); foreach (T o in this) collection.Add( (T) o.Clone() ); return collection; } object ICloneable.Clone() { return this.Clone(); } }
In C# 2.0, types can contain certain suffices to express additional compiler functionality:
<Type> - expresses a generic type, for example Collection<MyType> for a strictly typed collection.
? - expresses a value type that can contain a null value, for example
int myValue = null;
is impossible, but when declaring it as Nullable:
int? myValue = null;
it is possible. The question mark is actually a shorthand for the generic type Nullable<T>, so Nullable<int> and int? are in fact the same.
Too bad they didn't implement a NotNullable type for non-value types, using the ! (exclamation mark):
// doesn't compile MyType! myType = null;
This is however, it is implemented in the Cω Language (pronounced COmega), a C# variant with support for type-safe support for table and document manipulation (in other words: strictly typed SQL and strictly typed XML)
COmega also supports for the * (stream) operator. This might confuse C++ developers, however it has nothing to do with a pointer. The stream operator can be seen as a array, but of unspecified length, or a dynamic strictly typed (lazy) collection. If a type contains this suffix, it both implements the C# IENumerable (edit: was C# INumerable) and the IEnumerator interface, and the values are dynamically returned as the collection is iterated:
// generate s, s+1, ..., e
static int* FromTo(int s, int e) {
for (int i = s; i <= e; i++) yield return i;
}
public static void Main() {
int* OneToTen = FromTo(1,10);
// prints 1, ..., 10
foreach(int j in OneToTen){
Console.WriteLine(j);
};
}
In other words, the for-loop in FromTo, continues only if the next value is requested by the iterator. In this case the foreach loop through the entire collection, so for every value between 1 and 10 the for loop is executed. This creates great possibilities for ASynchronous communication like reading a large recordset from a database, because the next record is only fetched when it's requested, somewhat like the DataReader class, but in a strictly typed way.
And the point is...
Here I finally come to my point. Both the where and typeof keywords are essentially performing the same function, where I think the typeof isn't event necessary now, because there's no reason why this syntax shouldn't work, because MyType is already a type, why is the extra typeof() call necessary?
public MyType CreateInstance(Type type){ return (MyType) Activator.CreateInstance(type); } public static void Main(){ MyType instance = CreateInstance(MyType); // instead of // MyType instance = CreateInstance(typeof(MyType)); }
My proposal for C# 3.0 would be to replace them both with the Type# syntax, finally giving the # (pound) a function in C#, wich performs the same functionality as the Delphi "TMyTypeClass = class of TMyType" syntax.
Additionally, you would be able to use this as a typeof specifier in a method, and this could be our previous example rewritten, without having to specify:
public MyType CreateInstance(MyType# type){ return (MyType) Activator.CreateInstance(type); } public static void Main(){ MyType instance = CreateInstance(MyType); }
This could even give the previous ICloneableCollection<T> a easier to read look, and conforms more to the C# syntax:
//public class CloneableCollection<T> : Collection<T>, ICloneable where T : ICloneable public class CloneableCollection<ICloneable# T> : Collection<T>, ICloneable { public CloneableCollection<T> Clone() { CloneableCollection<T> collection = new CloneableCollection<T>(); foreach (T o in this) collection.Add( (T) o.Clone() ); return collection; } object ICloneable.Clone() { return this.Clone(); } }
And, last but not least, it would eliminate 2 extra keywords, wich must be important to Microsoft as well, because they're very proud of the low amount of keywords in C#.
I'd like to hear your comments on this.
5 Comments:
Smalltalk has all that.
Great... Don't work with Smalltalk though.
In answer to your question "where does C# get it's name from?", I've always thought that the pound suffix in C# was a continuation of the C++ joke/fun;
If you look closely at the '#' it is made up of 4 italic '+' plus signs. So I see it as C was incremented to become C++ and then C++ incremented (another set of '++' added) to become C#.
Maybe it's just me, and nobody else sees it that way, but if they meant it to be interpreted as that then it's a very witty name.
Yes, I've heard that theory before as well, it does seem the most likely to me.
I really dislike names anyway that have 'implicit pronounciations', i.o.w. non-alpha or single alpha characters pronounced as a word. (business2business, losew8, .net, c#, 1d84u2day, etc. etc.).
It's very localization- and search engine unfriendly, I still don't know wether to search for C#, CSharp or CPound ;-)
(for more perversions of C# see this post ;-) http://www.thedailywtf.com/forums/25129/ShowPost.aspx)
Hmm, I remember it was claimed somewhere on MS site that this sign is actually not a number/pound (#), but a music sharp, having really it's own typographical symbol.
Post a Comment
Subscribe to Post Comments [Atom]
<< Home