1 / 45

C# Language Design

C# Language Design. Peter Hallam Software Design Engineer C# Compiler Microsoft Corporation. Overview. Introduction to C# Design Problems Future Directions Questions. Hello World. using System; class Hello { static void Main() { Console.WriteLine("Hello, world!"); } }.

csilla
Download Presentation

C# Language Design

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C# Language Design Peter Hallam Software Design Engineer C# Compiler Microsoft Corporation

  2. Overview • Introduction to C# • Design Problems • Future Directions • Questions

  3. Hello World using System; class Hello { static void Main() { Console.WriteLine("Hello, world!"); } }

  4. C# Program Structure • Namespaces • Contain types and other namespaces • Type declarations • Classes, structs, interfaces, enums, and delegates • Members • Constants, fields, methods, operators, constructors, destructors • Properties, indexers, events • Organization • No header files, code written “in-line”

  5. Program Structure Example namespace System.Collections { using System; public class Stack: Collection { Entry top; public void Push(object data) { top = new Entry(top, data); } public object Pop() { if (top == null) throw new InvalidOperationException(); object result = top.data; top = top.next; return result; } } }

  6. Predefined Types • C# predefined types • The “root” object • Logical bool • Signed sbyte, short, int, long • Unsigned byte, ushort, uint, ulong • Floating-point float, double, decimal • Textual char, string • Textual types use Unicode (16-bit characters)

  7. C# Classes • Single inheritance • Can implement multiple interfaces • Members • Constants, fields, methods, operators, constructors, destructors • Properties, indexers, events • Nested types • Static and instance members • Member access • public, protected, internal, private

  8. Interfaces • Can contain method declarations; no code or data • Defines a “contract” that a class must support • Classes have one base class, but can implement many interfaces interface IFormattable { string Format(string format); } class DateTime: IFormattable { public string Format(string format) {…} }

  9. Statements and Expressions • Very similar to C++, with some changes to increase robustness • No ‘->’ or ‘::’; all qualification uses ‘.’ • Local variables must be initialized before use • if, while, do require bool condition • goto can’t jump into blocks • switch statement – no fall through • Expression statements must do something useful (assignment or call) void Foo() { void Foo() { i == 1; // error if (i = 1) // error } ...

  10. C# Design Goals • Simple, Extensible Type System • 1st Class Component Support • Robust and Versionable • Preserve existing investments

  11. Problem:How to Unify the Type System • A single universal base type (“object”) • All types ultimately inherit from object • Object variable can hold any value • Any piece of data can be stored, transported, and manipulated with no extra work • Unification enables: • Calling virtual functions on any value • Collection classes for any type

  12. Unifying the Type System Desired Picture: object Stream Hashtable int double MemoryStream FileStream • How to deal with the primitive types without losing performance? • How to create user-defined types that are as efficient as “int” or “double”?

  13. How to Unify:A traditional approach (SmallTalk) • Make everything a real object • Performance implications • All objects have a type descriptor or virtual function table • May require all object to be heap-allocated to prevent dangle pointers • Behavior and expectation mismatch • “int” variables can be “null”

  14. How to Unify:Don’t do it (Eiffel, Java) • Intrinsic types are not classes • Good performance • Can’t convert “int” to “Object” – the primitive types are in a separate world • Requires special wrapper classes (e.g., “Integer”) to “wrap” a primitive type so that it works in the “Object” world. • Not extensible – the set of primitive types is fixed.

  15. How to Unify:C# Approach • Types are divides into two kinds: Reference types and Value types • Reference types are full-featured: • Always allocated in heap • Arbitrary derivation • Value types have restrictions: • Only inherit from object • Can’t be used as base classes • Allocated from stack or inline inside other objects • Assignment copies value, not reference

  16. Unification • Value types don’t need type descriptors or vtables (efficient!) • “object” does need a type descriptor, because it can contain any type • Value types become reference types when they are converted to “object” • Value is copied to heap, type descriptor attached • Process is called “boxing” • When cast back to value type, “unboxing” occurs, value is copied out of heap

  17. 123 i } o “int” “Boxing” 123 ? } “Unboxing” j Boxing and Unboxing • “Everything is an object” • Any type can can be stored as an object int i = 123; object o = i; int j = (int)o; 123

  18. User-Defined Types • C# allows user-defined types to be either reference or value types • Classes (reference) • Used for most objects • Structs (value) • Objects that are like primitive data (Point, Complex, etc). struct Point { int x, y; ... } Point sp = new Point(10, 20);

  19. C# Type System • Natural User Model • Extensible • Performant

  20. Problem: Additional Declarative Information • How do you associate information with types and members? • XML persistence mapping for a type • External code interop information • Remoting information • Transaction context for a method • Visual designer information (how should property be categorized?) • Security contraints (what permissions are required to call this method?)

  21. Other Approaches • Add keyword or pragma • Requires updating the compiler for each new piece of information • Use external file • Information clumsy to find/see • Require duplication of names • Example: IDL files for remote procedures • Use naming patterns • Create a new class or constant that describes the class/members • Example: Java “BeanInfo” classes

  22. C# Solution: Attributes • Attach named attributes (with optional arguments) to language element • Uses simple bracketed syntax • Arguments must be constants of string, number, enum, type-name

  23. Attributes - Examples public class OrderProcessor { [WebMethod] public void SubmitOrder(PurchaseOrder order) {...} } public class PurchaseOrder { [XmlElement("shipTo")] public Address ShipTo; [XmlElement("billTo")] public Address BillTo; [XmlElement("items")] public Item[] Items; [XmlAttribute("date")] public DateTime OrderDate; } public class Button { [Category(Categories.Layout)] public int Width { get {…} set {…} } [Obsolete(“Use DoStuff2 instead”)] public void DoStuff() {…} }

  24. Attributes • Attributes • Attached to types, members, parameters, and libraries • Present in the compiled metadata • Can by examined by the common language runtime, by compilers, by the .NET Frameworks, or by user code (using reflection) • Extensible • Type-safe • Extensively used in .NET Frameworks • XML, Web Services, security, serialization, component model, transactions, external code interop…

  25. Creating an Attribute • Attributes are simply classes • Derived from System.Attribute • Class functionality = attribute functionality • Attribute arguments are constructor arguments public class ObsoleteAttribute : System.Attribute { public ObsoleteAttribute () { … } public ObsoleteAttribute (string descrip) { … } }

  26. Using the Attribute [Obsolete] void Foo() {…} [Obsolete(“Use Baz instead”)] void Bar(int i) {…} • When a compiler sees an attribute it: • Finds the constructor, passing in args • Checks the types of arguments against the constructor • Saves a reference to the constructor and values of the arguments in the metadata

  27. Querying Attributes • Use reflection to query attributes Type type = typeof(MyClass); foreach(Attribute attr in type.GetCustomAttributes()) { if ( attr is ObsoleteAttribute ) { ObsoleteAttribute oa = (ObsoleteAttribute) attr; Console.WriteLine(“{0} is obsolete: {1}”, type, attr.Description; } }

  28. Problem : Versioning • Once a class library is released, can we add functionality without breaking users of the class library? • Very important for system level components!

  29. Versioning Problems • Versioning is overlooked in most languages • C++ and Java produce fragile base classes • Users unable to express versioning intent • Adding a virtual method can break a derived class • If the derived class already has a method of the same name, breakage can happen

  30. Versioning: C# solution • C# allows intent to be expressed • Methods are not virtual by default • C# keywords “virtual”, “override” and “new” provide context • Adding a base class member never breaks a derived class • Adding or removing a private member never breaks another class • C# can't guarantee versioning • Can enable (e.g., explicit override) • Can encourage (e.g., smart defaults)

  31. Versioning Example class Base // version 1 { } class Base // version 2 { public virtual void Foo() { Console.WriteLine("Base.Foo"); } } class Derived: Base // version 1 { public virtual void Foo() { Console.WriteLine("Derived.Foo"); } } class Derived: Base // version 2a { new public virtual void Foo() { Console.WriteLine("Derived.Foo"); } } class Derived: Base // version 2b { public override void Foo() { base.Foo(); Console.WriteLine("Derived.Foo"); } }

  32. Interface Implementation • Private interface implementations • Resolve interface member conflicts interface I { void foo(); } interface J { void foo(); } class C: I, J { void I.foo() { /* do one thing */ } void J.foo() { /* do another thing */ } }

  33. foreach Statement • Iteration of arrays • Iteration of user-defined collections public static void Main(string[] args) { foreach (string s in args) Console.WriteLine(s); } foreach (Customer c in customers.OrderBy("name")) { if (c.Orders.Count != 0) { ... } }

  34. Extending foreachIEnumerable interface IEnumerable { IEnumerator GetEnumerator(); } interface IEnumerator { bool MoveNext(); object Current { get; } }

  35. Extending foreachIEnumerable foreach (int v in collection) { // use element v … } (IEnumerable) ie = (IEnumerable) collection; IEnumerator e = ie.GetEnumerator(); while (e.MoveNext()) { int v = (int) e.Current; … }

  36. foreach • Problems with IEnumerable • no compile time type checking • boxing when enumerating value types • Solution : A pattern-based approach • The C# compiler looks for: • GetEnumerator() on the collection • bool MoveNext() on the enumerator type • Strongly typed Current on the enumerator type

  37. foreach - Summary • Some Complexity • interface • pattern • Extensible • User collections can plug into foreach • User Model • Compile-time type checking • Performance • Value type access without boxing

  38. Future Directions

  39. Generics - Prototype • Implemented by MSR Cambridge • Don Syme • Andrew Kennedy • Published Paper at PLDI 2001

  40. Generics - Prototype class Stack<T> {T[ ] data; void Push(T top) { …} T Pop() { … } } Stack<string> ss = new Stack<string>; ss.Push(“Hello”); Stack<int> si = new Stack<int>; ss.Push(4);

  41. Other Approaches – C++ • Templates are really typed macros • Compile time instantiations only • Require source for new instantiations • Type Parameter Bounds Infered • Good Execution Speed • Bad Code Size

  42. Other Approaches - Java • Type Erasure • No VM modifications • Compile time type checking • No instantiations on primitive types • Execution Speed – Casts • Good Code Size • Type Identity Problems • List<String> vs. List<Object>

  43. C# .NET Generics Prototype • prototype .NET runtime is generics aware • All objects carry exact runtime type • Instantiations on reference and value types • Type Parameters bounded by base class and/or interfaces • Runtime performs specialization

  44. C# .NET Generics Prototype • Compile Time Experience • Separate compilation of generic types • Instantiations checked at compile time • Can Instantiate on all types – int, string • Runtime Experience • Dynamic Type Specialization • Execution Speed – No Extra Casts • Code Size – Code Sharing reduces bloat

More Related