What’s new in Visual Studio 2010 and C# 4.0
description
Transcript of What’s new in Visual Studio 2010 and C# 4.0
What’s new in Visual Studio 2010 and C# 4.0
Kirill OsenkovVisual Studio C# IDE Team
Language Features in C# 4.0
1. Dynamic2. Co-/Contravariance3. Named and Optional Arguments4. COM Interop Improvements
1. Dynamic – Late Binding in C#
Early binding:Console.WriteLine();
Late binding:typeof(Console).GetMethod("WriteLine").Invoke(null, null);
Static typing• Compiler checks members and types• IDE IntelliSense• Binding at compile time, exact
method baked into ILcall void [mscorlib]System.Console::WriteLine()
Dynamic typing• Member names, types and signatures
not known at compile time• JavaScript, IronPython, IronRuby• COM Interop Scenarios• Reflection over non-accessible types• Compiler can’t check correctness• Refactoring doesn’t work
Starting Visual Studio// Type is not known at compile timeType vsType = Type.GetTypeFromProgID("VisualStudio.Dte.10.0");
// create an instance dynamicallyobject instance = Activator.CreateInstance(vsType);
// get the property and hope it's therePropertyInfo property = vsType.GetProperty("Visible");
// call and pass weakly typed argumentsproperty.SetValue(instance, true, null);
Information in the code:// Type is not known at compile timeType vsType = Type.GetTypeFromProgID("VisualStudio.Dte.10.0");
// create an instance dynamicallyobject instance = Activator.CreateInstance(vsType);
// get the property and hope it's therePropertyInfo property = vsType.GetProperty("Visible");
// call and pass weakly typed argumentsproperty.SetValue(instance, true, null);
Information in the code:• In this object, set the ‘Visible’
property to trueobject
instance
SetProperty
Name: ‘Visible’
Value: ‘true’
Expressing call information in codeType vsType = Type.GetTypeFromProgID("VisualStudio.Dte.10.0");
BEFORE:
object instance = Activator.CreateInstance(vsType);PropertyInfo property = vsType.GetProperty("Visible");property.SetValue(instance, true, null);
AFTER:
dynamic instance = Activator.CreateInstance(vsType);instance.Visible = true;
How it works
instance.Visible = true;
How it works
… becomes …
How it worksif (<StartVSDynamic>o__SiteContainer0.<>p__Site1 == null){ <StartVSDynamic>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, bool, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "Visible", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));}<StartVSDynamic>o__SiteContainer0.<>p__Site1.Target.Invoke(<StartVSDynamic>o__SiteContainer0.<>p__Site1, instance, true);
Details• A DLR callsite object is created upon
first request• All the statically known callsite
information is encapsulated• Callsites are cached for performance
Bonus abstraction layer• A way to intercept dynamic calls and
plug in your own behavior• DynamicObject,
IDynamicMetaObjectProvider• TryGetMember, TrySetMember get
called when a member is called on the dynamic object
• ExpandoObject
Dynamic sample: Dictionarycolors.Blueinstead ofcolors["Blue"]
colors.Red = 0xFF0000;instead ofcolors.Add("Red", 0xFF0000);
Dynamic sample: XMLcustomer.Address.Street
instead ofcustomer.Element(“Address”).Attribute(“Street”).Value
Dynamic sample: XMLdynamic contact = new DynamicXMLNode("Contacts");contact.Name = "Patrick Hines";contact.Phone = "206-555-0144";contact.Address = new DynamicXMLNode();contact.Address.Street = "123 Main St";contact.Address.City = "Mercer Island";contact.Address.State = "WA"; contact.Address.Postal = "68402";
Dynamic Sample: Reflection• Before:var employee = new Employee();var members = employee.GetType().GetMember("age", MemberTypes.All, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);((FieldInfo)members[0]).SetValue(employee, 42);
• After:dynamic employee = (new Employee()).AsDynamic();employee.Age = 42;
2. Co/Contravariance• This feature is very hard to explain• You only need it once a month or less• When you do need it you do need it• It’s about passing around generic
interfaces and delegates only• Whatever you’d expect should work
now works
IN and OUT:
public Widget CreateWidget(string name);
“IN”“OUT”
Fails in C# 3:using System;
class Program{ static void Main(string[] args) { Func<string> stringFactory = () => "Hello"; Print(stringFactory); }
static void Print(Func<object> objectFactory) { object o = objectFactory(); Console.WriteLine(o); }}
Works in C# 4:using System;
class Program{ static void Main(string[] args) { Func<string> stringFactory = () => "Hello"; Print(stringFactory); }
static void Print(Func<object> objectFactory) { object o = objectFactory(); Console.WriteLine(o); }}
string
object
Func<string>
Func<object>
covariance
out == covariant
• Func is covariant in TResult• All about “producing” types• Func<T>, IEnumerable<T>, *Factory, *Creator
• Covariant interfaces and delegates in the BCL are annotated with ‘out’
public delegate TResult Func<out TResult>();
Fails in C# 3:using System;
class Program{ static void Main(string[] args) { Action<object> objectPrinter = Console.WriteLine; PrintHello(objectPrinter); }
static void PrintHello(Action<string> printer) { printer("Hello"); }}
Works in C# 4:using System;
class Program{ static void Main(string[] args) { Action<object> objectPrinter = Console.WriteLine; PrintHello(objectPrinter); }
static void PrintHello(Action<string> printer) { printer("Hello"); }}
string
object
Action<string>
Action<object>
contravariance
in == contravariant
• Action is contravariant in T• All about “consuming” types: Action<T>, IComparer<T>
• Contravariant interfaces and delegates in the BCL are annotated with ‘in’
public delegate void Action<in T>(T obj);
Co/Contravariant BCL Types• Covariance (“out”):– IEnumerable<Animal> is now assignable
from IEnumerable<Cat>– Func<Cat> is now also a Func<Animal>
• Contravariance (“in”):– A variable of type Action<Cat> (specific)
can now be assigned a value of type Action<Animal>(generic)
• http://msdn.microsoft.com/en-us/library/dd799517.aspx
Named argumentsdocument.Close(saveChanges: true);vs.document.Close(true);
• Arguments can now be specified out of order
• Code readability is improved• Warning: parameter names become part of API• Renaming a parameter in one assembly can
now break the code in another assembly
Optional arguments• Before:var app = new Application();var missing = Type.Missing;object fileName = "word.doc";app.Documents.Open( ref fileName, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
Optional arguments• After:var app = new Application();app.Documents.Open("word.doc");
COM improvements1. Omit ref2. No PIA3. Indexed properties
Omit ref on COM arguments• app.Documents.Close(missing);
instead of• app.Documents.Close(ref missing);
No PIA (Primary Interop Assemblies)
• PIAs are managed wrapper assemblies around COM types: EnvDTE, Microsoft.Office.Interop.Word, etc.
• Can embed the necessary parts in your program
• PIA doesn’t need to be distributed with your app
No PIA (Primary Interop Assemblies)
Indexed Properties• Before:
excel.get_Range("A1").set_Value(Type.Missing, "ID");
• After:excel.Range["A1"].Value = "ID";
Event implementation changes
• Before:[MethodImpl(MethodImplOptions.Synchronized)]public void add_MouseDown(Action value){ this.MouseDown =
(Action) Delegate.Combine(this.MouseDown, value);}
Event implementation changes
• After:public static void add_MouseDown(Action value){ Action action2; Action MouseDown = MouseDown; do { action2 = MouseDown; Action action3 =
(Action) Delegate.Combine(action2, value); MouseDown = Interlocked.CompareExchange<Action>
(ref MouseDown, action3, action2); } while (MouseDown != action2);}
C# IDE Features
C# IDE Features• Ctrl+,• Ctrl+K,T• Ctrl+Shift+Up/Down• Ctrl+.• Ctrl+Alt+Space
C# IDE Features• Navigate To• Call Hierarchy• Highlight References• Generate From Usage• IntelliSense improvements (consume-
first, sub-string and camelCase search)
Q & A• Kirill Osenkov• http://blogs.msdn.com/b/kirillosenkov• http://twitter.com/kirillosenkov
Bonus slides
Team Architect• Architecture Explorer• Sequence Diagrams• DGML – graph modeling
Debugger• IntelliTrace• Pinnable Data Tips• Thread Window improvements
(Freeze/thaw)• Parallel Debugging tool windows
Shell• WPF Shell• Multi-monitor support• Extension Manager
Editor• Brand new WPF text editor• Box-selection• Zoom, Ctrl+scroll
Shameless Plug:• My open-source projects:• http://livegeometry.codeplex.com• http://undo.codeplex.com• http://structurededitor.codeplex.com• http://layout.osenkov.com