• Kirill Osenkov

    Stress testing Visual Studio 2010

    • 18 Comments

    In the past several months Visual Studio and I have been really busy stress testing each other. This post is a general overview on what we've been up to and what kind of testing we're doing. I've learned a lot about stress testing and I have to say it's actually a lot of fun, so I guess it's worth sharing. I'll try to make this a series of several posts, diving into more technical details in the upcoming posts.

    Background

    During Beta 1 and Beta 2 it became painfully obvious that the new VS had an obesity problem: it was slow, consumed a lot of memory and the worst thing, with enough modules loaded it stopped fitting into the 2GB address space on 32-bit machines. There were several reasons for this, which Rico Mariani, Brian Harry and others have extensively blogged about. In a nutshell, with a lot of new functionality a lot more modules were loaded into memory. Besides, we now had to fully load the CLR and WPF at application startup. Moreover, there were all kinds of memory leaks all over the place.

    Making performance a top priority

    Of course this wasn't good, so our management made the right decision to make performance our top priority. Jason really took it seriously and we dedicated a lot of people to work fulltime to make Visual Studio fast and lean. As part of this effort I became a member of a virtual team called "Perf SWAT". This team is responsible for essentially three things: performance, memory consumption and design-time stress.

    Performance is clear: we need to be fast. Memory consumption is clear too: when we load, we need to take as little memory as possible, and avoid things such as double-loaded modules, loading both NGEN and IL versions of an assembly, and so on.

    Design-time stress on the VSL team

    As for design-time stress, the goal is once we're loaded into memory, jitted, warmed up and all the caches are filled, we should not continue to grow in consumption. This means find and eliminate all memory and resource leaks. Run-time stress means finding leaks in the CLR and BCL, design-time stress means finding leaks in the VS and tooling. I am responsible for design-time stress testing for the VSL team (managed languages). I need to make sure that there are no significant leaks in 4 areas:

    1. C# IDE and editor integration (C# code editor, navigation, refactorings and other core C# areas)
    2. VB IDE and editor integration
    3. F# IDE
    4. Hostable Editor (Workflow Designer in VS 2010 is essentially hosting a full-blown language service to show IntelliSense in the expression editor on the workflow diagram)

    Progress

    The good news is that we've made tremendous progress since Beta 2 and have brought the product into a much better state: it is much faster, more responsive, takes up much less memory and we also hope to have eliminated all major known memory leaks. A common complaint was that VS was growing in memory during usage and you had to restart it after a certain time. Right now we hope that you can mostly keep Visual Studio open for days (even weeks) without having to restart it.

    8 hour stress tests

    The official sign-off criteria is that the end user needs to be able to keep VS open for an entire work week without any noticeable performance degradation (this means 5 days times 8 hours a day). We've calculated that in average continuous human usage of 40 hours is equivalent to running our tests for 8 hours (tests are doing things faster than a human).

    We have identified and implemented a series of 22 tests for all the 4 language teams mentioned above. Each test covers one continuous kind of activity, e.g. CSharpStressEditing, CSharpStressNavigation, CSharpStressIntelliSense, CSharpStressDebugging, CSharpStressUI, VBStressEditing, VBStressProjectSystem, FSharpStressEditing, and so on.

    Each test runs for 8 hours on a machine in the lab and VS memory usage details are automatically logged. We've also developed tools to automatically analyze the stress logs and produce Excel spreadsheets and charts for analysis and reporting.

    Several months ago a typical test would start at about 300 MB ProcessWorkingSet and crash after several hours with OOM (Out-Of-Memory exception). None of the tests would even be able to run for 8 hours. After finding and fixing a lot (a lot!) of bugs, we were able to get it running for 8 hours – VS memory usage grew from about 300-400 MB of WorkingSet to over 1 GB over the period of 8 hours (that was anywhere from 200-500 stress iterations).

    Right now a typical test starts at about 150-200 MB and finishes 8 hours later at 200-300 MB. Also, instead of 500 iterations, it is able to do 3000-5000 iterations during 8 hours on the same hardware. Which means we made it considerably faster and also reduced the leaks in major feature areas to a minimum (right now a feature is considered not leaking if there is average increase of less then ~5KB per iteration).

    I'll try to continue blogging about our stress testing and dive more into the technical details: what we measure, how we measure, how we find bugs and how we'll know when we're eventually done.

  • Kirill Osenkov

    Unable to cast COM object … to IVsGlobalUndoCapableUndoManager

    • 3 Comments

    Hi all, sorry for the absense – we're all really busy fixing Visual Studio 2010 performance, memory consumption, improving stability and fixing last minute bugs.

    Good news: if you're seeing this:

    Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.VisualStudio.Editor.Implementation.IVsGlobalUndoCapableUndoManager'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{305E8709-55B7-4732-B872-1C073AB58047}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

    then we know what's going on.

    Workaround

    Try running devenv.exe /nosplash to bypass the splash screen, and things should work fine.

    WOOT??! How is the splash screen related??! :)

    For the curious ones, here's what's happening:

    …In my case I was investigating a fairly popular (5-6 new hits a day) Watson bucket. Ultimately I’ve found out, using some DistSvcs extension for WinDbg, that every dump has the splash screen thread as its main STA, followed by a crash. The symptoms are almost exactly the same as yours – IlocalRegistry::CreateInstance used on the WinMain thread, and returns a proxy for the newly created object. It seems to be a race condition between main thread and splash screen thread as to which one calls CoInitializeEx first (including implicit calls via various Win32 APIs), since we spin off the splash thread before we explicitly call OleInitialize (which calls CoInitialize) on the main thread.

    After a LOT of investigations, the solution was finally found by Pavel Minaev and Michael Lehenbauer, developers on the Visual Studio platform team. Huge thanks goes to them and to Viacheslav Ivanov, who helped a lot by reporting the issue and providing valuable call stacks, minidumps and trying out various things for us!

  • Kirill Osenkov

    Visual Studio 2010 Beta 2 Known Issues – Part 2

    • 23 Comments

    This post continues my unofficial list of known issues in VS 2010 Beta 2 (see Part 1). As we continue getting Beta 2 feedback and investigating issues, it's time for another update on the issues we've been seeing. Please keep in mind that due to the volume of the issues, I'm only mentioning the ones I was involved with or consider important.

    Crash during normal editor operation

    There is a rare situation where Beta 2 can crash during normal editing or viewing C# source code. Nevertheless, it happens often enough to become top 1 reported crash for C#.

    I'm very happy to say that we have identified the root cause and are working on a fix.

    Details: This is an extremely complex and hard to reproduce bug involving native code, threading, and working with Task Parallel Library from native code. The new C# IDE feature, Highlight References, is written in managed code and uses TPL (Task Parallel Library) to calculate references on a threadpool thread. However a certain portion of the language service (called the Language Analysis engine) is written in native code, so we had to do some cross-boundary and cross-thread manupulation. Our developers Ian (from C# compiler) and HeeJae (from C# IDE) worked very very hard to investigate the dumps that you folks were sending in and finally they've found the bug. The good news is that as more and more of Visual Studio gets rewritten in managed code, we hope to see less of such bad bugs in the future.

    So thanks to you for clicking that "Send Error Report" button – it really helped us to fix the top 1 reported C# crash!

    Cannot open C# source file: Error message "The operation could not be completed. Invalid pointer." or "Object reference not set to an instance of an object"

    This one is due to the Tools Options Fonts and Colors using a raster font instead of a TrueType font:

    http://blogs.msdn.com/visualstudio/archive/2009/10/27/VS-2010-Beta2_3A00_--Workaround-for-Raster-Font-Settings-Issue.aspx

    The fix is easy: switch to a TrueType font such as Consolas or Courier New.

    The editor team has fixed this one already.

    The application cannot start (VS black screen)

    Weston writes about this one in detail: http://blogs.msdn.com/visualstudio/archive/2009/10/29/how-to-fix-the-application-cannot-start-error.aspx 

    This is due to us being unable to read certain profile settings.

    The workaround is basically to run devenv /resetuserdata from the Visual Studio command prompt, but I encourage you to follow the link above for more information (e.g. how to save your settings beforehand).

    This is already fixed as well (now even if the profile contains the errors we will start successfully and deal with the errors).

    TextOptions does not appear in the IntelliSense in XAML designer

    The WPF team has completely rewritten the WPF text rendering to get rid of the font blurryness issue. The old style is still the default, to enable the new mode you need this simple attribute in your XAML: TextOptions.TextFormattingMode="Display". The problem is – TextOptions won't show up in IntelliSense!

    The workaround is to ignore IntelliSense and just build your project – things should just work.

    This has been fixed as well.

    All menus except the File menu disappear

    It happens extremely rarely, but we saw it three times already – the menus are just gone!

    image

    This one is very very hard to reproduce and we're still investigating this right now – for some unknown reason something is messing up the Style or the ControlTemplate for the menus. If you happen to run into this inside a virtual machine, you can really help us investigate the issue by pausing the machine in the state where VS is running and menus are gone.

    Feel free to open a bug on http://connect.microsoft.com/visualstudio/feedback or let me know and we'll send you instructions on how to upload the VM image.

    Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.VisualStudio.Editor.Implementation.IVsGlobalUndoCapableUndoManager'.

    ---------------------------

    Microsoft Visual Studio

    ---------------------------

    Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.VisualStudio.Editor.Implementation.IVsGlobalUndoCapableUndoManager'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{305E8709-55B7-4732-B872-1C073AB58047}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

    ---------------------------

    OK

    ---------------------------

     

    Right now we can't reproduce it so we're looking for any help – call stack, minidump with heap, ActivityLog.xml etc. You can read more about the ActivityLog here:

    http://msdn.microsoft.com/en-us/library/ms241272.aspx

    We'd appreciate any help!

    Expression.Compile generates incorrect code for (int?) conversion

    using System;
    using System.Linq.Expressions;
    
    class Program
    {
        static void Main()
        {
            Expression<Func<ValueType, int?>> expr = x => (int?)x;
            Func<ValueType, int?> converter1 = x => (int?)x;
            Func<ValueType, int?> converter2 = expr.Compile();
    
            int? a1 = converter1(null); // (int?) null
            int? a2 = converter2(null); // NRE
        }
    }

    Expected: both the direct delegate and the one generated with Expression Trees should work identically. Actual: the expression tree one throws a NullReferenceException.

    Thanks to controlflow for reporting this! It's a good bug, but unfortunately it will require a risky compiler change that we don't want to take so late in the product cycle. We've postponed the bug for a later release.

    Delegate.Combine doesn't support variance

    using System;
    
    class A { }
    class B : A { }
    
    class Program
    {
        static void Main()
        {
            Action<B> b = _ => { };
            Action<A> a = _ => { };
            b += a;
        }
    }

     

    This program compiles fine but causes an exception at runtime. The CLR team decided to postpone this to a future version.

    Completion List doesn't show up for certain lambda parameters in multiple overload scenarios

    using System;
    
    using System.Linq;
    using System.Threading.Tasks;
    
    class Program
    {
        static void Main(string[] args)
        {
            var query = Enumerable.Range(0, 100);
            Parallel.ForEach(query, (i, p) =>
            {
                Console.WriteLine(i);
                p.
            });
        }
    }

     

    In this code, IntelliSense doesn't show after p. Another great bug from controlflow. We've fixed this one (it had to deal with picking the right overload of ForEach given an incomplete lambda statement).

    Debugger data tips are leaking GDI handles

    Hovering the mouse cursor over variables during debugging and expanding the nodes in the tips will leak GDI handles. After the Visual Studio process will run out of GDI handles (and each process can only allocate 10,000 handles), it will crash. Usually this happens after 10-15 minutes of intensive debugging with datatips, depending on circumstances. You can watch the GDI handles of the devenv.exe process in the Task Manager (if you select GDI in View –> Select Columns).

    This is a stress bug that has been fixed by the debugger team recently.

    Tooltips on toolbar buttons are not displaying keyboard shortcuts

    As part of the WPF rewrite, we had postponed this work until very late, and only recently have fixed it (post Beta 2). Now all the keyboard shortcuts show up when you hover your mouse over a toolbar button. You will not be able to turn them off though :)

    Printing formatted source code with color is not supported

    This is actually not a bug, it's by design. We had to cut this low-impact feature from 2010 because of tight resources constraints as we've reimplemented the editor from scratch. This feature will hopefully come back in a later release of Visual Studio, maybe as an add-in.

    More High DPI and other accessibility issues

    I just keep finding more and more High DPI issues, hoping that if I find and report them now, you guys won't have to.

    Combobox missing right edge:

    image

    The shell team decided not to fix this because of tight schedule and resources.

    Snippets background poorly visible on High Contrast Black

    image

    The editor team has decided not to fix this because the colors are configurable.

    Silverlight Out-of-Browser settings dialog clips some controls under 120 DPI

    We're looking into fixing this right now.

  • Kirill Osenkov

    A million-dollar pen vs. a pencil

    • 5 Comments

    You know this legend about how NASA spent millions to develop a pen that can write in zero gravity, and the russians have just used a pencil? Well, I was reminded about this by Dejan’s post in response to my post about the Random Gradient Wallpaper Generator.

    I used an O(NxN) algorithm to generate a megapixel image that takes up about 5 MB on my desktop.

    Dejan generated a 2x2 bitmap that takes up 70 bytes and let Windows stretch it with the exactly same effect. If you read my original post, go read this one, you’ll like it :)

  • Kirill Osenkov

    Bezier Curves and Car Manufacturers

    • 3 Comments

    Michael has asked me if it was possible to add Bezier curves to Live Geometry. So I went ahead and added a Bezier tool (and it took me about 30 minutes to do so!):

    image

    This draws a cubic Bezier curve using four points:

    image

    There is something beautiful and elegant about these curves. No wonder industrial designers use it a lot. I actually felt so inspired that I went ahead and used the tool to design a car :) Here's the live view (you need Silverlight 3 to see this), and you can drag the points around:

    This is so fascinating. Maybe if I'm tired of programming I should just design cars? ;) Any recruiters from Subaru reading this?
     
    I also built in a possibility to pass arguments to Live Geometry using initParams:
    <object data="data:application/x-silverlight-2," 
    type="application/x-silverlight-2" width="100%" height="100%">
      <param name="source" value="LiveGeometry.xap"/>
      <param name="initParams" 
             value="LoadFile=http://guilabs.de/geometry/drawings/fun/car.lgf,ShowToolbar=false" />
    ...

    That's how I was able to embed Live Geometry into this page so that it doesn't show the toolbar and it automatically loads the car.lgf drawing.

    Finally, here are some important things to know if you want to host a .xap file from another domain:

    • That domain must have crossdomain.xml at its root (so http://livegeometry.com/crossdomain.xml should be accessible)
    • If you're testing this by loading an .html file from a local filesystem, it will just display a white background and won't load the app. Put the .html on a webserver, then it will work
  • Kirill Osenkov

    Irony

    • 7 Comments

    (Ironically, this post is not about irony in it's traditional sense)

    Irony (http://irony.codeplex.com) is an open-source .NET compiler construction framework written by Roman Ivantsov. It is a ".NET Language Implementation Toolkit". The language grammar is described in C# (or any other .NET language).

    So instead of generating the scanner and the parser from a grammar description written in an external DSL, Irony uses a .NET object graph to host the grammar description (internal DSL), and it uses this in-memory grammar description to drive the scanner and the parser at runtime.

    One huge advantage of this approach is that the language description becomes orthogonal to the scanner and parser implementation. Writing and maintaining a language becomes easier. See an example of grammar definition further down in this post.

    Arithmetic expression evaluation

    The reason I'm talking about all this is that I was looking around for an expression parser for Live Geometry. I was able to compile expressions earlier using DLR, but there were two issues with that.

    1. First, DLR has quite a footprint – adding a dependency on DLR to a Silverlight binary can grow the size of the .xap file from 400 KB to 1400 KB – and that's not good.
    2. Second, DLR didn't seem to expose the parse trees easily – and I do need the access to the parse trees for inspection and manipulation, such as calculating dependencies between formulas.

    So I started looking around. There are really a lot of related projects out there, I'll just mention the ones on CodePlex:

    1. http://antlrcsharp.codeplex.com
    2. http://csparser.codeplex.com
    3. http://expressioneval.codeplex.com
    4. http://flee.codeplex.com
    5. http://ilcalc.codeplex.com
    6. http://lazyparser.codeplex.com
    7. http://linqovercsharp.codeplex.com
    8. http://ncalc.codeplex.com
    9. http://simpleexpressioneval.codeplex.com
    10. http://simplemathparser.codeplex.com
    11. http://expressionscompiler.codeplex.com

    There might be more. My requirements were for the tool to output a parse tree and give me full access to it. Another requirement is that the grammar description has to be as simple as possible and as flexible and extensible as possible (because I planned to extend the language with custom elements such as method calls and property access). However full blown C# and LINQ parsers were an overkill. Other good projects were really fast, but didn't give me the parse tree.

    So I settled on Irony, and so far I'm pretty happy that I did. It didn't provide the Silverlight version out of the box, but I'm talking with Roman about Silverlight support. For now, it took me an hour to make the Irony sources build for Silverlight and I built a nice little Irony.Silverlight.dll for my own project.

    Expression parser in Irony

    Here's how I declared the grammar for the language that I need:

    // This grammar is based on the ExpressionEvaluatorGrammar from Irony.Samples
    // Copyright (c) Roman Ivantsov
    // Details at http://irony.codeplex.com
    [Language("Expression", "1.0", "Dynamic geometry expression evaluator")]
    public class ExpressionGrammar : Irony.Parsing.Grammar
    {
        public ExpressionGrammar()
        {
            this.GrammarComments = @"Arithmetical expressions for dynamic geometry.";
    
            // 1. Terminals
            var number = new NumberLiteral("number");
            var identifier = new IdentifierTerminal("identifier");
    
            // 2. Non-terminals
            var Expr = new NonTerminal("Expr");
            var Term = new NonTerminal("Term");
            var BinExpr = new NonTerminal("BinExpr");
            var ParExpr = new NonTerminal("ParExpr");
            var UnExpr = new NonTerminal("UnExpr");
            var UnOp = new NonTerminal("UnOp");
            var BinOp = new NonTerminal("BinOp", "operator");
            var PostFixExpr = new NonTerminal("PostFixExpr");
            var PostFixOp = new NonTerminal("PostFixOp");
            var AssignmentStmt = new NonTerminal("AssignmentStmt");
            var AssignmentOp = new NonTerminal("AssignmentOp");
            var PropertyAccess = new NonTerminal("PropertyAccess");
            var FunctionCall = new NonTerminal("FunctionCall");
    
            // 3. BNF rules
            Expr.Rule = Term | UnExpr | FunctionCall | PropertyAccess | BinExpr;
            Term.Rule = number | ParExpr | identifier;
            ParExpr.Rule = "(" + Expr + ")";
            UnExpr.Rule = UnOp + Term;
            UnOp.Rule = ToTerm("+") | "-" | "++" | "--";
            BinExpr.Rule = Expr + BinOp + Expr;
            BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "^";
            PropertyAccess.Rule = identifier + "." + identifier;
            FunctionCall.Rule = identifier + ParExpr;
            this.Root = Expr;
    
            // 4. Operators precedence
            RegisterOperators(1, "+", "-");
            RegisterOperators(2, "*", "/");
            RegisterOperators(3, Associativity.Right, "^");
    
            RegisterPunctuation("(", ")", ".");
            MarkTransient(Term, Expr, BinOp, UnOp, AssignmentOp, ParExpr);
        }
    }

    That's it! Note how Irony uses operator overloading for | and + to build rules. We need ToTerm("+") call on any of the operands to give the C# compiler a hint about the types so the operator overloading can succeed. This is a good example of an internal DSL hosted in C#.

    Consuming the parse tree

    Now, here's how to use the ExpressionGrammar class to create and use a parser:

    Grammar grammar = new ExpressionGrammar();
    Parser parser = new Parser(grammar);
    ParseTree parseTree = parser.Parse("sin(2 * x) + 1");

    Producing a LINQ Expression Tree from a parse tree

    Now, given the parse tree from the previous step, I just quickly wrote an ExpressionTreeBuilder that produces a bound expression tree out of it, and a Binder that helps resolve names. The Compiler class is a façade for the whole thing:


    public class Compiler
    {
        public static Func<double, double> CompileFunction(string functionText)
        {
            ParseTree ast = ParserInstance.Parse(functionText);
            ExpressionTreeBuilder builder = new ExpressionTreeBuilder();
            Expression<Func<double, double>> expression = builder.CreateFunction(ast.Root);
            Func<double, double> function = expression.Compile();
            return function;
        }
    
        static Parser ParserInstance = new Parser(ExpressionGrammar.Instance);
    }
    
    
    public class Binder { public void RegisterParameter(ParameterExpression parameter) { parameters.Add(parameter.Name, parameter); } ParameterExpression ResolveParameter(string parameterName) { ParameterExpression parameter; if (parameters.TryGetValue(parameterName, out parameter)) { return parameter; } return null; } Dictionary<string, ParameterExpression> parameters = new Dictionary<string, ParameterExpression>(); public Expression Resolve(string identifier) { return ResolveParameter(identifier); } public MethodInfo ResolveMethod(string functionName) { foreach (var methodInfo in typeof(System.Math).GetMethods()) { if (methodInfo.Name.Equals(functionName, StringComparison.InvariantCultureIgnoreCase)) { return methodInfo; } } return null; } }

    public class ExpressionTreeBuilder
    {
        public ExpressionTreeBuilder()
        {
            Binder = new Binder();
        }
    
        public Binder Binder { get; set; }
    
        public Expression<Func<double, double>> CreateFunction(ParseTreeNode root)
        {
            ParameterExpression parameter = Expression.Parameter(typeof(double), "x");
            Binder.RegisterParameter(parameter);
            Expression body = CreateExpression(root);
            var result = Expression.Lambda<Func<double, double>>(body, parameter);
            return result;
        }
    
        Expression CreateExpression(ParseTreeNode root)
        {
            if (root.Term.Name == "BinExpr")
            {
                return CreateBinaryExpression(root);
            }
    
            if (root.Term.Name == "identifier")
            {
                return Binder.Resolve(root.Token.Text);
            }
    
            if (root.Term.Name == "number")
            {
                return CreateLiteralExpression(Convert.ToDouble(root.Token.Value));
            }
    
            if (root.Term.Name == "FunctionCall")
            {
                return CreateCallExpression(root);
            }
    
            return null;
        }
    
        Expression CreateCallExpression(ParseTreeNode root)
        {
            string functionName = root.ChildNodes[0].Token.Text;
            Expression argument = CreateExpression(root.ChildNodes[1]);
            MethodInfo method = Binder.ResolveMethod(functionName);
            return Expression.Call(method, argument);
        }
    
        Expression CreateLiteralExpression(double arg)
        {
            return Expression.Constant(arg);
        }
    
        Expression CreateBinaryExpression(ParseTreeNode node)
        {
            Expression left = CreateExpression(node.ChildNodes[0]);
            Expression right = CreateExpression(node.ChildNodes[2]);
    
            switch (node.ChildNodes[1].Term.Name)
            {
                case "+":
                    return Expression.Add(left, right);
                case "-":
                    return Expression.Subtract(left, right);
                case "*":
                    return Expression.Multiply(left, right);
                case "/":
                    return Expression.Divide(left, right);
                case "^":
                    return Expression.Power(left, right);
            }
            return null;
        }
    }

    This just demonstrates the principle. One could easily extend this to write a full blown expression compiler, but this is good enough for my purposes for now. Live Geometry now uses this to evaluate math expressions and plot function graphs. As always, you can get the source from here.

  • Kirill Osenkov

    Indexed Properties in C# 4.0

    • 12 Comments

    Executive summary:

    1. In C# 4.0 you can call parameterized properties declared in COM using the indexer syntax, for instance instead of excel.get_Range("a") you can now write excel.Range["a"].
    2. You can’t declare your own indexed properties from C#. We have no plans of adding the ability to declare your own properties with parameters. Instead, the recommended way is to use a type with an indexer.
    3. The feature is immediately available in Visual Studio 2010 Beta 2 for your indexing pleasure.

    So I guess this hasn’t had a lot of press coverage so far (although Sam hinted about it). Even the published C# 4.0 language specification and the C# Future page still don’t mention it as of now. This is because we’ve implemented this feature very late in the cycle, as a DCR (Design Change Request). The language design team felt that we should complete the COM interop story in 4.0 and this one was the last missing piece of the puzzle. When Paul was in Redmond this summer, he was tasked with testing the IDE support for this feature, and I was helping out with the test infrastructure.

    The new syntax

    The pattern is very simple. Wherever you use COM interop and have to call get_X() and set_X(), now you can just call X[], which we feel is a more natural syntax:

    // before
    excel.get_Range("A1").set_Value(Type.Missing, "ID");
    
    // after
    excel.Range["A1"].Value = "ID";

    Let’s also take Scott Hanselman’s example from Beta 1:

    var excel = new Excel.Application();
    excel.Visible = true;
    excel.Workbooks.Add();
    excel.get_Range("A1").Value2 = "Process Name";
    excel.get_Range("B1").Value2 = "Memory Usage";

    Now you can simplify this even further:

    var excel = new Excel.Application();
    excel.Visible = true;
    excel.Workbooks.Add();
    excel.Range["A1"].Value = "Process Name";
    excel.Range["B1"].Value = "Memory Usage";

     

    This is just syntactic sugar – the compiler emits calls to the get_ and set_ accessors behind the stage.

    Omitting []

    In case that all the parameters are optional and none of the arguments are specified, you should omit the empty []. Having Value[] is illegal.

    This is the reason you can replace Value2 with Value in the example above: Value is an indexed property and you’re calling it without specifying any arguments – in this case we omit the brackets [] altogether. Earlier, without indexed properties support, we had to introduce the ugly Value2, because you otherwise had to call get_Value().

    IDE support

    My team, on the IDE side, provided IntelliSense support for this new language feature:

    • completion list:

    image

    • parameter help:

    image

    • however Quick Info still shows you that in reality the call simply binds to the get_Range method:

    image

    As we were designing the feature, it turned out that adding compiler support for it is not the only tricky part. There were a couple of interesting problems in the IDE space as well. For example, what do you show in Quick Info for the following intexed property call?

    A.B[C]++;

    Do we now show get_B or set_B?

    When the IDE can’t guess which accessor we’re talking about (for example, in incomplete code), we by default bind to the get_accessor.

    Backwards compatibility

    For backwards compatibility reasons, using the accessors get_ and set_ directly is still valid and available in IntelliSense, because we didn’t want to break all existing COM interop code out there.

    Why not allow declaring indexed properties in C#?

    A common question that we expect we’ll be getting is “why just consume? why not allow to declare such properties in C#?”. Well, the answer is not even that we first have to cost, design, spec, prototype, implement and test this feature, but rather that we think that declaring a type with an indexer is a preferred approach. It’s useful to separate the responsibilities:

    • The property is there to get an object. The property belongs to the parent object.
    • The indexer is there on the returned object to enumerate it. The indexer belongs to the returned object.

    We shouldn’t be mixing these together.

    Static or dynamic?

    Accessing indexed properties is supported from both static and dynamic code.

    kick it on DotNetKicks.com
  • Kirill Osenkov

    Visual Studio 2010 Beta 2 Known Issues

    • 14 Comments

    [This is Part 1. Read Part 2 here]

    Now that we’ve shipped Beta2 and the world is busy downloading the fresh new bits, I’m very excited to know what do you guys think? Will you like it? Will there be major issues that we missed? Time will show :)

    By definition, this Beta 2 release is not final, and there are still bugs lurking around out there. We are very busy fixing those bugs for RTM, but for now, there are some that we haven’t had time to fix before Beta2.

    This post lists some of the known issues that are in VS 2010 Beta 2. It’s not in my powers to maintain a comprehensive list here, I’ll just mention the ones which I was personally involved with in my day-to-day work. Apologies that I have found them too late, but I guess better late then never...

    Updates – new!

    Posted the Part 2 of the issues (updated 11/12/2009)

    http://blogs.msdn.com/kirillosenkov/archive/2009/11/12/visual-studio-2010-beta-2-known-issues-part-2.aspx

    All further updates will happen there or will wait until Part 3.

    The official Beta2 known issues list (updated 10/26/2009)

    http://go.microsoft.com/fwlink/?LinkID=166199

    Updating the .sln file from Beta1 to Beta2 (updated 10/26/2009)

    Need to upgrade .sln file from Beta2 in order to be able to double-click it. See Jon’s post here for more details:

    http://msmvps.com/blogs/jon_skeet/archive/2009/10/26/migrating-from-visual-studio-2010-beta-1-to-beta-2-solution-file-change-required.aspx

    Setup dialog UI layout wrong on High DPI

    image

    Embarrassing! Unfortunately, not everyone on the Visual Studio team is rigorous about non-default testing, such as High DPI, Accessibility, etc. We will hopefully fix this one before RTM. Also recent data shows that non-96 DPI is a very common setting, a lot of people actually use 120 DPI and others. I personally use 120 DPI, that’s how I find these bugs.

    SmartTag high DPI issues

    image

    With high DPI, the SmartTag menu is missing horizontal menu separator bars. Also the right vertical edge of the SmartTag button disappears. These bugs are a recent regression from WPF introducing the UseLayoutRounding API. The WPF team is looking into fixing these issues before the release.

    QuickInfo tooltip trimmed at high DPI

    image

    This is another regression from the new DWrite technology. The last word in the tooltip is missing! This one is fixed already.

    Thin line on top of the active document tab

    image

    Again, another high DPI issue. You can only notice this one if you look closely. We’ve fixed this already as well.

    Outlining Expand/Collapse glyphs are shifted several pixels up

    image

    Fixed already. A lot of people complained about this internally.

    Zoom combobox in the bottom-left corner of the editor isn’t aligned with the horizontal scrollbar

    image

    This is fixed.

    Don’t tear off the Call Hierarchy tool window!

    When you try to undock the C# Call Hierarchy toolwindow and drag it away (for example, to another monitor), VS will crash. This one is too embarrassing, because I was the one who is responsible for testing Call Hierarchy. To my defense, I was on vacation when this regressed and when I came back and found this, it was too late to fix. Shell UI team changed something about the WPF toolwindow implementation and we had some layout logic that didn’t expect double.Infinity as an argument, so we crashed. This one’s already fixed in recent builds.

    Vertical separator bar in the Call Hierarchy tool window doesn’t resize the details pane

    This also only reproes under 120 DPI and above. You can’t resize the two panes below by dragging the vertical bar:

    image

    And again, this is one that I should have caught and missed. When I caught this, it was too late to fix for Beta2. The WPF team is looking at this one right now.

    Error message connecting to a TFS server via HTTPS

    Well, guess what, the TFS client team has done it again! TFS HTTPS story was broken in Beta1, and it still has a bug in Beta2. However the good news is that there is a really easy workaround this time.

    When adding a new TFS HTTPS webserver (e.g. a Codeplex server at http://codeplex.com), after entering your credentials you will see this:

    image

    Don’t panic! Just enter your credentials again and things will work just fine. If you used the Tip (http://blogs.msdn.com/kirillosenkov/archive/2009/09/27/tip-don-t-enter-your-codeplex-credentials-every-time.aspx), then you will be unaffected by this and things will hopefully run smoothly.

    Ctrl+Alt+DOWN ARROW doesn’t bring up the active document list

    Ctrl+Alt+Down used to bring up the active document list, in Beta2 it doesn’t. This is fixed.

    Start Page: scroll wheel doesn’t work at the news feed

    Also the scrollbar thumb only moves in discrete steps. The Shell UI team decided not to fix this, because they don’t have time and resources for this. I actually was surprised to discover that the scrollbar didn’t work in 2008 either. Never noticed this until recently.

    VS Command prompt shortcut is not getting installed if you don’t install C++

    This one will be fixed as well.

    Hovering over ‘var’ during debugging doesn’t show the inferred type

    Jeffrey Richter told me about this minor annoyance. Although our language service correctly reports the inferred type when you hover the mouse cursor over ‘var’ in design time, it doesn’t work in debug mode. Since Jeff teaches a lot of courses in debugging and threading, this was bugging him ever since we shipped C# 3.0. Well, we finally fixed it for 2010 RTM. Thanks to Jeff for reporting this!

    Visual Studio doesn’t start maximized when first launched

    A while back I’ve logged a bug against the Shell team to “just start VS maximized for heaven’s sake”. They did the fix, but somehow it didn’t make it into the Beta2 branch. They’ll hopefully fix this for RTM.


    Well, these were the ones worth mentioning I guess. Apologies if you run into any of these or any other bugs for that matter. I will keep updating this post with more issues that I find or I think users should be aware of. Please keep in mind that this is an unofficial list.

    Please do let us know about any issues you find by submitting a connect bug. If the bug/suggestion/feedback is related to the C# language or IDE, also feel free to let me know directly or leave a comment on this blog. Since I work closely with the VS editor team, it’s worth watching their blog and giving them feedback: http://blogs.msdn.com/vseditor. Also, if you have any feedback about the new text rendering in WPF 4.0 and Visual Studio, the WPF Text team has a blog here: http://blogs.msdn.com/text.

  • Kirill Osenkov

    Saving images (.bmp, .png, etc) in WPF/Silverlight

    • 10 Comments

    I’ve recently added a new feature to Live Geometry that allows users to save the current drawing as a bitmap or a .png file. Just push the save button and pick the desired image format in the Save dialog:

    image

    Fortunately, both WPF and Silverlight support saving full visual contents of any visual into a file on disk. However the approach is somewhat different.

    Saving images in WPF

    WPF can save any Visual to an image and it supports several formats out of the box via a concept of Encoders. Here’s a sample for .bmp and .png:

    void SaveToBmp(FrameworkElement visual, string fileName)
    {
        var encoder = new BmpBitmapEncoder();
        SaveUsingEncoder(visual, fileName, encoder);
    }
    
    void SaveToPng(FrameworkElement visual, string fileName)
    {
        var encoder = new PngBitmapEncoder();
        SaveUsingEncoder(visual, fileName, encoder);
    }
    
    void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder)
    {
        RenderTargetBitmap bitmap = new RenderTargetBitmap(
            (int)visual.ActualWidth,
            (int)visual.ActualHeight,
            96,
            96,
            PixelFormats.Pbgra32);
        bitmap.Render(visual);
        BitmapFrame frame = BitmapFrame.Create(bitmap);
        encoder.Frames.Add(frame);
    
        using (var stream = File.Create(fileName))
        {
            encoder.Save(stream);
        }
    }

    These types are all in System.Windows.Media.Imaging.

    Saving images in Silverlight 3

    In Silverlight, the encoders don’t come as part of the Silverlight runtime – but fortunately there is a project on CodePlex called ImageTools (http://imagetools.codeplex.com) that provides necessary support. You will need to download the following binaries and add them as references to your Silverlight project:

    • ICSharpCode.SharpZipLib.Silverlight
    • ImageTools
    • ImageTools.IO
    • ImageTools.IO.Png (only if you want .png support)
    • ImageTools.IO.Bmp (only if you want .bmp support)
    • ImageTools.Utils

    After that, you can call the ToImage() extension method on any Canvas:

    void SaveAsPng(Canvas canvas, SaveFileDialog dialog)
    {
        SaveToImage(canvas, dialog, new PngEncoder());
    }
    
    void SaveAsBmp(Canvas canvas, SaveFileDialog dialog)
    {
        SaveToImage(canvas, dialog, new BmpEncoder());
    }
    
    void SaveToImage(Canvas canvas, SaveFileDialog dialog, IImageEncoder encoder)
    {
        using (var stream = dialog.OpenFile())
        {
            var image = canvas.ToImage();
            encoder.Encode(image, stream);
        }
    }

    Since you can’t write to disk directly in Silverlight, you can pass a SaveFileDialog and use its stream, or you can obtain a stream elsewhere and pass that. The ToImage() extension method does the dirty work that we had to do ourselves in WPF.

    Big thanks to http://imagetools.codeplex.com for their awesome library and encoders!

  • Kirill Osenkov

    Links

    • 0 Comments

    There are several good folks out there who regularly accumulate interesting links about all things .NET and other stuff on their blogs (cast in alphabetical order):

    Alvin Ashcraft

    Alvin Ashcraft's Morning Dew

    .NET Development Resources from a Progressive.NET Perspective

    Arjan Zuidhof

    Arjan’s World

    Arjan Zuidhof’s opinionated linkblog, with a hang to Alt.NET

    Charlie Calvert

    Charlie Calvert's Community Blog

    Charlie is the C# Community Program Manager on our team and has a great series called “Community Convergence”. I hope he never runs out of roman numerals :)

    Chris Alcock

    Reflective Perspective

    The caffeine fueled thoughts of a UK Software Developer and home of ‘The Morning Brew’

    Jason Haley

    Interesting Finds

    Ramblings of a .Net developer
    .ver 3:0:0:0

    Scott Guthrie

    ScottGu’s Link Listing tag

    Yes, ScottGu is a linkblogger!

    Steve Pietrek

    A Continuous Learner’s weblog

    My continuous learning of .NET, C#, VB.NET, ASP.NET, Delphi, Business Intelligence, Software Design and Development, Project Management, Object Oriented Development, Unit Testing, Development Tools ramblings....

    And since I feel a little linkbloggy myself today, here it goes:

  • Kirill Osenkov

    Visual Studio 2010 New Editor screenshot

    • 18 Comments

    I’m very happy with how the Visual Studio editor improved since Beta1:

    image

    This is all WPF and includes the WPF 4.0 text rendering changes (DWrite integration). Note the new Zoom combobox in the bottom-left (which is the visual counterpart of Ctrl+ScrollWheel). Also the cross to close the tab is now located ON the tab, and not on the rightmost edge of the document. It takes about a day to get used to, but after you get used to it, it’s really awesome.

    I believe that the editor team has done a phenomenal job making the editor better for all of us. Note that although the screenshot was made from a remote desktop to a virtual machine, it still looks much better than in Beta1. And believe me, it is way faster and more reliable now.

    I’m very excited for Beta2 and can’t wait to get the bits out for you to play with!

  • Kirill Osenkov

    Random Gradient Wallpaper Generator

    • 10 Comments

    Oops, I did it again :) Created a new CodePlex project, that is.

    Introducing http://wallpaper.codeplex.com – a simple tool to generate a nice random wallpaper and display it on your desktop with just one click:

    WallpaperGenerator1.png

    WallpaperGenerator3

    • Randomize - assigns random colors to all four corners
    • Set as Wallpaper - saves the picture to My Pictures\GradientWallpaper.bmp and sets the Windows Desktop wallpaper to this file. It will overwrite the file if it exists.
    • Save colors to text file - appends the RGB values of the current colors to the "colors.txt" log file in the program's directory (in case you liked the colors and want to save the colors, not the image)
    You can also click on each of the four corners and pick any color yourself. There are a total of 79228162514264337593543950336 possible wallpapers that can be generated this way.

    WallpaperGenerator4WallpaperGenerator5WallpaperGenerator6WallpaperGenerator7WallpaperGenerator8WallpaperGenerator9WallpaperGenerator10WallpaperGenerator11

    I wrote this in an evening a couple of years ago and it was just lying around, so I decided to publish it so that it doesn’t get lost. Of course, one could take WPF, MEF, Bling, pixel shaders and build it out into a super-extensible plug-in-based photoshop-like fractal-ray-tracing rendering wallpaper generator, but... For now, let’s stick with a simple WinForms app. But hey, it’s open source, feel free to contribute if you like ;)

  • Kirill Osenkov

    Dump Environment Folder Paths

    • 7 Comments

    This is just a quick snippet to dump the value of Environment.GetFolderPath for all special folders on a machine (so I don’t have to write it again next time):

    public static string DumpEnvironmentPaths()
    {
        var paths = Enum.GetValues(typeof(Environment.SpecialFolder))
            .Cast<Environment.SpecialFolder>()
            .Select(folder => folder + " = " + Environment.GetFolderPath(folder))
            .Aggregate((line1, line2) => line1 + Environment.NewLine + line2);
        return paths;
    }

    Also, I’m using the opportunity to give Rick Strahl’s CodePaste.NET service a spin: http://codepaste.net/uo7zx8.

    “CodePaste.NET is a public site for pasting snippets of code and linking to them from social network sites.”

    As for the code itself (envisioning potential rotten tomatoes flying my way), several things are probably worth mentioning:

    1. First, the code is written in a more functional style, being more explicit about its intent. I think it shows more clearly the input data and the output data, how the data flows and what operations are performed on the input data.
    2. Second, I have a temporary local variable instead of returning the expression immediately. This is for easier debugging, because if you don’t have a temporary variable, you won’t be able to view the return value of the method easily in the debugger. With a temporary local, you can put a breakpoint on the return statement and inspect the results of the query. Someday the tools will be improved and will allow to inspect the return value of methods.
    3. I’m using Aggregate instead of string.Join or StringBuilder because it composes better. On large data volumes, this approach is horrible because it will allocate a ridiculous amount of unnecessary intermediate strings. StringBuilder and string.Join are much more frugal in this respect, so don’t use Aggregate with strings this way. However, in this particular example, the number of strings is O(1), so I just picked the approach that composes better. Unfortunately, string.Join doesn’t compose well at all and was never intended to be used in a fluent API.
  • Kirill Osenkov

    Tip: Don’t enter your CodePlex credentials every time

    • 0 Comments

    I just ran across an awesome tip at Scott’s blog that is going to save me a whole lot of time: Save Your Codeplex Repository Credentials

    I was entering my username and password everytime I connected to a CodePlex TFS server. Now I don’t have to!

    P.S. To make this work on XP, go to Control Panel –> User Accounts –> click your account –> in the leftmost pane click Manage My Network Passwords:

    image

    image

  • Kirill Osenkov

    ColorPicker Control for WPF/Silverlight

    • 8 Comments

    A while back I was looking around for a color picker control for Live Geometry. The ColorPicker from http://silverlightcontrib.codeplex.com was exactly what I was looking for:

    Get Microsoft Silverlight

    (live preview needs Silverlight 3.0)

    Using the control in your code

    I just took the source from CodePlex and embedded it in my project. You need 5 files:

    image

    Alternatively, you can reference the binary which you can download from the SilverlightContrib CodePlex project site. Pay attention that generic.xaml contains the template for the control, so don’t forget the xaml. The control will work just fine with WPF and Silverlight, which is really a great thing, especially if you’re multitargeting.

    To include the control in your application, here’s the basic code:

    <sc:ColorPicker SelectedColor="LightGreen" />

    Don’t forget to add an XML namespace:

    xmlns:sc="clr-namespace:SilverlightContrib.Controls"

    How does the gradient work?

    The source code for this control is very good for educational purposes. For instance, I had no idea how they create the big gradient for every possible hue. Well, it’s genius and it’s simple. In generic.xaml:

    <Canvas Canvas.Top="0" Canvas.Left="20">
        <Rectangle x:Name="ColorSample" Width="180" Height="180" Fill="Red"></Rectangle>
        <Rectangle x:Name="WhiteGradient" IsHitTestVisible="False" Width="180" Height="180">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                    <GradientStop Offset="0" Color="#ffffffff"/>
                    <GradientStop Offset="1" Color="#00ffffff"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle x:Name="BlackGradient" IsHitTestVisible="False" Width="180" Height="180">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,1" EndPoint="0, 0">
                    <GradientStop Offset="0" Color="#ff000000"/>
                    <GradientStop Offset="1" Color="#00000000"/>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Canvas x:Name="SampleSelector" IsHitTestVisible="False" Width="10" Height="10" Canvas.Left="100" Canvas.Top="96">
            <Ellipse Width="10" Height="10" StrokeThickness="3" Stroke="#FFFFFFFF"/>
            <Ellipse Width="10" Height="10" StrokeThickness="1" Stroke="#FF000000"/>
        </Canvas>
    </Canvas>

    This canvas contains layers like in a cake. ZIndex of objects is stacked bottom to top, so the solid rectangle with initially red background is on the bottom.

    Above it, there is a horizontal white gradient fill, completely white on the left and completely transparent on the right.

    Above it, there is a vertical black gradient fill, completely black on the bottom and completely transparent on the top.

    As these gradients overlay, the transparency over the initial solid background creates the desired effect – the actual color is in top-right, where both gradients are 100% transparent. The white spot is in top-left, where the white gradient is most intense and black gradient fades out. Same for the black edge of the gradient.

    Also, it is well worth studying how the template is written – I learned a lot from this sample.

    My fixes

    Since I conveniently borrowed the source code for my project, I did several fixes for my own purposes. Ideally I should contribute the fixes back to SilverlightContrib, but I can never get around to it.

    First of all, I reordered the two StackPanels in the template so that the actual selected color is on top. I also made it collapsible and collapsed by default. You can expand the control by clicking it like a combobox. Unlike a combobox, you have to explicitly click the color area to collapse it again.

    Get Microsoft Silverlight

    I’ve enabled this by adding an Expanded property:

    public bool Expanded
    {
        get
        {
            return m_chooserArea.Visibility == Visibility.Visible;
        }
        set
        {
            var visibility = value ? Visibility.Visible : Visibility.Collapsed;
            if (m_chooserArea.Visibility == visibility)
            {
                return;
            }
            m_chooserArea.Visibility = visibility;
        }
    }

    When clicking on the color area, I just call Enabled = !Enabled to toggle it and it does the magic for me. The default value for this is obviously the default visibility of m_chooserArea, which is specified in XAML template (Visibility=”Visible” to set to true by default).

    Other fixes are not as interesting. I fixed a division by zero in ColorSpace.ConvertRgbToHsv (they had h = 60 * (g - b) / (max - min); and didn’t check if min == max). There are a couple of other things which I don’t remember off the top of my head. I’d have to view TFS history to remember what those were. If you’re willing to help and incorporate these fixes to the original project, I’ll dig this up, just let me know :)

    Conclusion

    Both Sara Ford and myself agree that this control deserves both thumbs up:

    image

  • Kirill Osenkov

    Reflection with dynamic

    • 0 Comments

    This past summer the Visual C# IDE team was fortunate enough to have Paul van Brenk intern with us. Paul is a great guy and an experienced .NET developer from Rotterdam, Netherlands, who is interested in Azure, cloud computing and many other things. He also happens to be one of the contributors for dasBlog, which I think is seriously cool.

    Paul and I were sharing an office during his internship and I was the “coach”, i.e. the guy who gets to answer all intern’s questions and helps figure things out :)

    Anyway, once we were talking about how to simplify the mess of calling private members using reflection and dynamic came into conversation. So Paul went ahead and wrote some C# 4.0 code that greatly simplifies calling private members using dynamic. Check out his blog: http://www.paulvanbrenk.com/blog/2009/05/30/UsingDynamicForEvil.aspx

    There are several things I’d like to shed more light on.

    Dynamic usage scenarios

    It’s a common misconception that dynamic can only be used for narrow interop scenarios. People came up with ways to use dynamic in a lot more scenarios.

    A common theme emerges from such usages: delay the name resolution (binding) to runtime. Instead of hardcoding the symbols known to compiler, we just specify source strings that have to be used at a later stage at runtime for lookup.

    Dynamic gives you nicer syntax to express member calls – you express them in your code using usual C# syntax (but without type checking), and the compiler does the heavy lifting of “quoting” the code down to the runtime. If you inspect the generated code, you will see that the compiler is taking your neat member call syntax and generating a complex call site data structure that contains metainformation about the call.

    How the language design team designed the dynamic feature

    From previous versions of C# you will notice that the language design team is clever when adding new features. They don’t just hardcode a feature into the language, they define an interface and implement the feature against that interface. Not literally, mind you. On the contrary, they rather use duck-typing in most cases, but still there is a contract defined somewhere and the feature works against that contract. Let me give a couple of examples:

    • foreach – they could have added foreach just to arrays. Instead, they “designed against an interface” and said: foreach will work against any IEnumerable implementation. Moreover, the contract of the feature is actually broader and is specified using duck-typing and not an explicit interface. foreach actually works against anything that has a GetEnumerator method, it does not have to implement IEnumerable. The extensibility here is that you can plug-in your own enumerator whatever it is and foreach will work just fine with it.
    • LINQ – again, the language design team said: query syntax will just translate into a well-defined set of methods (Select, Where, etc.). The extensibility here is that you can define your own Select, Where, etc. and LINQ will rewrite the query expressions against your own methods – the queries will continue to just work with your own implementation of the query pattern.
    • dynamic – and here, in C# 4.0, they didn’t just add dynamic. They defined an abstraction layer (an interface) that allows you to plug in your own implementation and the feature (dynamic) will work fine with it.

    In other words, they encapsulated an object with runtime callable members into an interface (IDynamicMetaObjectProvider) and provided default base implementation (DynamicObject). What this gives you is the ability to plug in your own implementation and dynamic will work against it.

    Effectively, this means that you can intercept member calls on any object, if these calls are dynamic. The secret of “abusing” dynamic is to use member call syntax for stuff other than calling a method. By redefining DynamicObject members you handle member calls in any way you want (usually some sort of lookup by string) – dictionary lookup, XML element and attribute lookup, reflection MemberInfo lookup, and so on.

    Now whether this all is good or bad is a totally separate discussion.

  • Kirill Osenkov

    First videos of the structured editor prototype

    • 15 Comments

    Disclaimer: the structured editor work described in my posts is unrelated to my work at Microsoft. Everything shown is my personal research done as part of my MSc thesis during 2004-2007. Also, it’s not ready for real use and does not cover all the features of even C# 1.0. It’s a concept prototype and work in progress.

    Introduction

    As part of my research back in school I was building an experimental structured editor for C#. Now I’ve decided to publish the sources and binaries on CodePlex:

    http://structurededitor.codeplex.com

    A detailed discussion of structured editors deserves a separate post, which is coming soon. For now, to give a better idea of how the editor works, I’ve recorded six short videos showing the different features below. If your blog reader doesn’t support iframes, I recommend you view this post in the browser.

    What is a structured editor?

    Programs are represented as text by most code editors. Structured editors, on the contrary, directly display the syntax tree of a program on screen and allow the user to manipulate the tree directly (think MVC: program parse tree is a model, the editor displays a view of it):

    This way the visual layout better illustrates the structure of the program and allows for atomic operations on the language constructs. A structured editor lets developers avoid syntax errors and concentrate on the meaning of the program instead of formatting.

    1. Introduction

    2. Editing

    You will notice that there is no intellisense and coloring at the expression level – I did build a SharpDevelop add-in that hosts the structured editor control inside the SharpDevelop project system (DOM), but these videos were recorded on a stand-alone version of the structured editor control hosted inside an empty windows form. Also the support at the expression level is rudimentary, because so far I’ve concentrated the most at declaration level (namespaces, types, members) and statement level (except for single-line statements such as assignments).

     

    3. Drag & Drop Support

    4. No Parser Means Less Syntax

    5. Properties

    6. Modifiers

    Background

    Structured editing is a topic surrounded with scepticism and controversy for the past 20-30 years. Some argue that directly editing the AST on screen is inflexible and inconvenient, because the constraints of always having a correct program restrict the programmer way too much. Others expect structured editors to be more helpful than text editors because the user operates atomically and precisely on the language constructs, concentrating on the semantics and not on syntax.

    In summer 2004, my professor Peter Bachmann initiated a student research project - we started building a structured editor for C#. I took part because I was deeply persuaded that good structured editors can actually be built, and it was challenging to go and find out for myself. After the original project was over, I took over the basic prototype and evolved it further to the state it is today.

    As one of numerous confirmations for my thoughts, in 2004, Wesner Moise wrote:

    ...I see a revolution brewing within the next three years in the way source code is written.

    Text editors are going to go away (for source code, that is)! Don't get me wrong, source code will still be in text files. However, future code editors will parse the code directly from the text file and will be display in a concise, graphical and nicely presented view with each element in the view representing a parse tree node. ...

    I remember how I agreed with this! After three years, in 2007, the prototype implementation was ready - it became the result of my master's thesis. I still agree with what Wesner was envisioning in 2004 - with one exception. Now I believe that structured editors shouldn't (and can't) be a revolution - fully replacing text editors is a bad thing to do. Instead, structured editors should complement text editors to provide yet another view on the same source tree (internal representation, or AST).

    My conclusions about structured editors

    1. Text-based editors aren’t going away anytime soon.
    2. Structured editors can only succeed by evolution, not revolution – hybrid approach and ability to toggle between text and structure is the way to go.
    3. The main difficulty with structured editors is getting the usability right.
    4. The right approach is solving all the numerous little problems one by one – find a solution for every situation where a text editor is better (from my experience, for any advantage of a text editor, a good structured solution can be found).
    5. You need a graphical framework with auto-layout such as WPF to build a structured editor.
    6. Don’t try to build a universal editor editor that can edit itself – this approach is too complex. Take a specific language and build a hardcoded editor for this language first. Only after you’ve built 2-3 successful editors, it makes sense to generalize and build a universal editor or an editor generator.
    7. Compilers shouldn’t be a black box, but expose the data structures as a public API surface.
    8. Syntax trees should be observable so that the editor can databind to them.
    9. Traditional expression editor should be hostable inside a structured editor for single-line statements and expressions.

    As a result of my work, I'm convinced that structured editors actually are, in some situations, more convenient than text editors and providing the programmer with two views on the code to choose from would be a benefit. Just like Visual Studio Class Designer - those who want to use it, well, just use it, and the rest continues to happily use the text editor. All these views should co-exist to provide the programmer with a richer palette of tools to chooce from.

    Hence, my first important conclusion. A program's internal representation (the AST) should be observable to allow the MVC architecture - many views on the same internal code model. With MVC, all views will be automatically kept in sync with the model. This is where for example something like WPF data-binding would come in handy.

    As for the structured editor itself - it is still a work in progress and I still hope to create a decent complement for text editors. It has to be usable and there are still a lot problems to solve before I can say: "Here, this editor is at least as good as the text editor". But I managed to solve so many challenging problems already, that I'm optimistic about the future.

    Current implementation

    The current implementation edits a substantial subset of C# 1.0 - namespaces, types, members (except events), and almost all statements. If you're interested, you can read more at http://www.guilabs.net and www.osenkov.com/diplom - those are two sites I built to tell the world about my efforts. I also accumulate my links about structured editing here: http://delicious.com/KirillOsenkov/StructuredEditors

    More languages

    It turned out that it makes sense to build structured editors not only for C#, but for other languages as well - XML, HTML, Epigram, Nemerle, etc. That is why, at the very beginning, the whole project was split in two parts - the editor framework and the C# editor built on top of it.

    Links

    1. http://structurededitor.codeplex.com
    2. http://guilabs.net
    3. http://www.osenkov.com/diplom
    4. http://delicious.com/KirillOsenkov/StructuredEditors

    If you want to know more, or if you want to share your opinion on this, please let me know. I welcome any feedback! Thanks!

    kick it on DotNetKicks.com Shout it
  • Kirill Osenkov

    UI without code or XAML: PropertyGrid, DataForm, etc.

    • 2 Comments

    WPF has certainly advanced the state-of-the-art in programming the UI. I personally think that WPF and Silverlight remove all the limits that existed to UI development in the past. The only limit now is your imagination. XAML is there for declarative machine-friendly UI descriptions, data-binding is for easier logic of syncing the UI to the data, automatic layout saves you all the trouble of aligning controls yourself, and so on.

    One thing that I notice though is that if your goal is a simple dialog or a wizard page, one is likely to write more code than is absolutely necessary, be it in a .NET language or XAML. For instance, one of the most trendiest patterns nowadays, MVVM, suggests that you have a model, a ViewModel (a UI-aware wrapper around model classes) and a View (that is databound to ViewModel). It is also suggested that you write some XAML to achieve what you need.

    My personal impression is that UI development nowadays has become complicated. It's super powerful, yes, but I find it is hard to find a simple solution for a simple scenario.

    For the purpose of this article, suppose that we need to implement a person editor dialog, and our business logic describes a person like this:

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    One is now likely to open XAML and start adding a Grid or a StackPanel with a couple of TextBoxes and databind them to the properties of the Person class. This approach is fine with me in general (since it decouples the UI from the domain model), however what I find is that it's just complicated and for simple scenarios might be an overkill.

    One other approach is often forgotten.

    PropertyGrid

    WinForms introduced an excellent control which unfortunately is probably less known and less used than it deserves: the PropertyGrid. You just add this control to your form and you just say:

    propertyGrid1.SelectedObject = joe;

    and you get:

    image

    What happens is that property grid reflects over the "editable" properties on the object, and displays each property as a separate row in the grid. Depending on the type of the property, it's value can be editable, additional controls can be displayed, for example, a color picker for colors, a calendar for DateTime, a checkbox for bool, etc. The nice thing about the design of the property grid (and I do think that the WinForms PropertyGrid is a very well designed control) is that if you have your own type, then you can also provide your own editor control for properties of that type.

    Also, the property grid provides certain other services - grouping properties into collapsible categories, description for selected property, multi-object selection (which enables setting a property on multiple objects simultaneously), etc.

    From the design perspective, what the property grid gives you is the ability to not duplicate the description of the UI. In the XAML example above you essentially describe your UI twice: first in your domain model (Name, Age) and then in your XAML (TextBox, TextBox) and then you bind the two together. With a property grid, on the contrary, you just declare your UI once, in your domain model, and you don't have to write any UI at all - property grid generates the UI for you.

    Unfortunately, this promising approach didn't go much further in the WinForms world, probably because of the limitations of the WinForms architecture (you couldn't re-style the property grid editors, rearrange rows or significantly customize its appearance (besides choosing the background and foreground colors and fonts).

    Silverlight 3 DataForm

    Thankfully, Silverlight 3 starts to fill the gap in the direction of eliminating the UI code by introducing the DataForm control: you can watch a great video by Mike Taulty about the DataForm here: http://beta.silverlight.net/learn/videos/silverlight-videos/dataform-control/ (and by the way, Mike Taulty makes excellent, excellent videos, highly recommended).

    Silverlight 3 DataForm comes with the free Silverlight Toolkit (http://silverlight.codeplex.com), is located in the assembly System.Windows.Controls.Data.DataFormToolkit.dll (GAC'ed) and works almost exactly like the WinForms PropertyGrid:

    image

    which results from this code:

    dataForm.CurrentItem = joe;

    I'm not aware of such a control for WPF but I haven't actually looked. All I know that it's a cool and promising approach which makes UI programming simpler, especially if you're designing dialogs, wizard pages or property grids.

    My own experiments

    Before Silverlight 3 came out, I was looking for an elegant way to implement property editing for the geometric figures in Live Geometry:

    image

    Since I didn't want to write any XAML for every property of every figure, I decided that the PropertyGrid design was a perfect fit, so I just implemented my own Property Grid (The benefit of having a hobby project is that you can use it as a playground and sandbox for experimenting with new ideas and approaches).

    The API is almost the same as the ones mentioned above:

    PropertyGrid.Show(this.Style, this.Drawing.ActionManager);

    gives you this:

    image

    Unlike the previous ones though, apart from the actual object being edited you can pass the second argument - a pointer to the ActionManager from my Undo Framework, which will make sure all the edits are recorded in the Undo history and can be undone.

    Metadata

    An important decision in the design of my property grid was to abstract away from modeling UI elements as CLR metadata. Both PropertyGrid and DataForm use CLR metadata (properties and their types) to encode what controls do we want to show on the form. Although metadata is very good for this (especially enriched with the .NET attributes as additional declarative mechanism, such as the [Description] attribute), I wanted to abstract away how the UI intent is declared, just like MEF can abstract away how a contract is specified. This was also inspired by the introduction of ICustomTypeDescriptor that allows extensibility of the PropertyGrid along the dimension of the property set. I didn't like metadata as the host language for the declaration of my UI elements, neither I liked XAML, for various reasons. So I came up with a basic interface called IValueProvider that encapsulates any value, be it a value of a CLR property or a value of a method's parameter, or anything else that might come up in the future. Here's a rough sketch (design not finalized yet):

    public interface IValueProvider
    {
        event Action ValueChanged;
        void RaiseValueChanged();
        T GetValue<T>();
        bool CanSetValue { get; }
        void SetValue<T>(T value);
        object Parent { get; }
        Type Type { get; }
        string Name { get; }
        string DisplayName { get; }
        T GetAttribute<T>() where T : Attribute;
        IEnumerable<T> GetAttributes<T>() where T : Attribute;
    }

    This gives me extensibility along the dimension of how UI elements are declared.

    Discovery

    To solve the task of taking content (think: an object) and extracting a set of editable values from it (think: properties), I introduced a so-called ValueDiscoveryStrategy. IncludeByDefaultValueDiscoveryStrategy will include all the properties unless they're marked with the [Ignore] attribute, and ExcludeByDefaultValueDiscoveryStrategy will exclude all the properties unless they're marked with the [PropertyGridVisible] attribute. Right now the discovery strategies only support CLR metadata (object properties and method parameters), but in the future nothing prevents me from adding more strategies to create editable values off of something else, say columns of a table in a database schema. This gives me the extensibility along the dimension of what properties to show in the grid.

    As an example, here's the ShapeStyle class that is being displayed in the screenshot above:

    public class ShapeStyle : LineStyle
    {
        public override FrameworkElement GetSampleGlyph() {...}
    
        Color mFill = Colors.Yellow;
        [PropertyGridVisible]
        public Color Fill
        {
            get
            {
                return mFill;
            }
            set
            {
                mFill = value;
                OnPropertyChanged("Fill");
            }
        }
    
        public override Style GetWpfStyle() {...}
    }

    The Fill property comes in here, and Color and Stroke width are inherited from LineStyle.

    Editors

    An editor is essentially a visual control that can edit an IValueProvider. For different types of values there are different kinds of editors. It's just a textbox for a string property, a checkbox for bools, a color picker for Color, etc. The nice thing (again, borrowed from the WinForms property grid design) is that the pool of editors is extensible. I use homemade dependency injection to discover all types of editors available for a type and instantiating a proper editor for a proper type. This gives me extensibility along the dimension of what types of properties can I edit.

    Also at this point kudos go to SilverlightContrib folks for an excellent ColorPicker control that I reused in my app! Great job and many thanks! BTW I fixed two bugs in it which I think I should submit as patches... need to remind myself later...

    Anyway, here's all it took to add an editor type for properties of type System.Windows.Color:

    public class ColorEditorFactory 
        : BaseValueEditorFactory<ColorEditor, Color> { }
    
    public class ColorEditor : LabeledValueEditor, IValueEditor
    {
        public ColorPicker Picker { get; set; }
    
        protected override UIElement CreateEditor()
        {
            Picker = new ColorPicker();
            Picker.SelectedColorChanging += ColorChanged;
            return Picker;
        }
    
        void ColorChanged(object sender, SelectedColorEventArgs e)
        {
            SetValue(e.SelectedColor);
        }
    
        public override void UpdateEditor()
        {
            Picker.SelectedColor = GetValue<Color>();
            Picker.IsEnabled = Value.CanSetValue;
        }
    }

    Complex types

    There are two approaches for displaying properties of complex types: either expanding them in place just like a tree view item gets expanded (and collapsed), or providing a hyperlink that, when clicked, will display that object's properties in the PropertyGrid, instead of the current one. In the latter case, one will probably want to implement some sort of a back button that will display the original object.

    Method Caller Buttons

    Finally, why not move it one step further? If we can get and set properties using this property grid, why not support calling methods? Here's a screenshot again of the polygon properties - note the three buttons at the bottom. They're generated too!

    image

    Here's the full source for the buttons:

    [PropertyGridVisible]
    public virtual void Delete() { ... }

    As you see, just add the [PropertyGridVisible] on any method and it will appear in the UI. Obviously, pushing the button will call the method.

    [PropertyGridVisible]
    [PropertyGridName("Create new style")]
    public void CreateNewStyle()
    {
        Drawing.ActionManager.SetProperty(this, "Style", 
            Drawing.StyleManager.CreateNewStyle(this));
        EditStyleButton();
    }
    [PropertyGridVisible]
    [PropertyGridName("Edit style")]
    public void EditStyleButton()
    {
        if (PropertyGrid != null)
        {
            PropertyGrid.Show(this.Style, this.Drawing.ActionManager);
        }
    }

    The next logical step is to allow calling methods with arguments. For example, having this method on your type:

    [PropertyGridVisible]
    public void AddEntry(Person person, DayOfWeek day, bool check)
    {
    }

    will result in this UI:

    image

    Clicking the button will call the method and pass the current values as arguments. This button is implemented as a simple button with PropertyGrid content that displays MethodInfo's parameters instead of object's property values (it uses a different ValueDiscoveryStrategy called ParameterDiscoveryStrategy).

    Summary

    Using this approach we can build a UI library for calling APIs. You design an API and you get a (basic) UI for it for free. This library will allow us to inspect any object at runtime similar to how debugger watch windows allow us to do it. Moreover, we can not only inspect it, but also set the property values and call methods on objects. This might prove useful not only for dialogs, wizard pages, property browsers, but possibly in other scenarios where you're editing a data structure directly and don't really care about customizing the default UI.

    I'm currently planning to continue evolving this prototype library as part of the Live Geometry source code, and possibly spawn off a separate project when this library becomes more mature and if there is demand.

    For now, if you're interested in the source code, you can find the up-to-date implementation at http://livegeometry.codeplex.com/SourceControl/ListDownloadableCommits.aspx -> Main\DynamicGeometryLibrary\PropertyGrid.

    Let me know if you have any questions or feedback. Thanks!

  • Kirill Osenkov

    www.officelabs.com and Garage: How Microsoft Supports Grassroots Innovation

    • 0 Comments

    This post was originally aimed for Microsoft employees who also have a side project, or a hobby project. It turns out, we have a nice internal thing called “The Garage” that is aimed to specifically support and foster such “evenings- and weekends projects” by Microsoft employees.

    Garage: What they do
    I own a side project (plug: http://livegeometry.codeplex.com) and Garage did a free usability study for it, which was really awesome. They organized everything (including free food), invited participants, prepared the task lists and helped to actually conduct the usability study. This was a great experience – I actually watched three MS employees work with Live Geometry and listen to their feedback, thoughts, comments as they discover and use the software.

    Usability study

    I realized that Live Geometry is still far from being intuitive and there are a lot of things that I can improve. I’ve gathered a lot of valuable information which I was able to convert to more than 50 actionable bugs! Another useful experience that I gained is how to conduct a good usability study. I've learned the following:

    • Be friendly and thankful for the participant's time. They're doing you a favor.
    • It's not a test for the participant's skills, it's a test for the usability of the software.
    • Don't talk, don't reveal how things work, don't answer questions too early.
    • Don't let them struggle too much, help them out when they're really stuck.
    • The participant is always right and your software is always wrong :)
    • Whatever feedback they give is good feedback.
    • Don't forget to write things down.
    • Show them how it's supposed to work at the end, it's likely you'll be rewarded with a "wow" :)

    Other Garage events

    Garage organizes a range of other events: Stay Late and Code (pizza provided), Improve a Project (where they demo projects and gather user feedback), Speed-dating for innovators (they bring together the folks who need help on a project and folks who would like to participate in a project or help out), help with hosting a project, etc.

    Productivity Science Fair

    Also recently I participated in a semi-annual company-wide exhibition called the Productivity Science Fair. It generated a lot of interest and was very crowded (actually, a lot of people stopped by my booth, wanted to learn more about my project and left their contact info - I ended up collecting more than 50 e-mail addresses of those who were interested!). I literally never spend more than one minute without someone stopping by, almost lost my voice at the end of the day. But it was so much fun!

    So, if you’re a Softee AND have a side project or projects, do check out http://garage and/or add yourself to the ‘garage’. At this point – huge thanks to Quinn Hawkins and Jennifer Michelstein for their engagement!

    What’s there for non-Microsofties? www.officelabs.com

    I wouldn’t blog about this at all if there wasn’t some goodness for folks external to Microsoft. Well, guess what, some of those side projects eventually become external so you can benefit too! Check out http://www.officelabs.com, especially the Grassroots Innovation projects: http://www.officelabs.com/Pages/Grassroots.aspx?category=grassroots for a sample of several projects already out there. Garage is actually sponsored by Office Labs and it's nice to see innovation being fostered both internally and externally.

    Microsoft Education Labs - www.educationlabs.com

    One other thing Quinn from the Garage team was helping me with is getting in touch with folks from Microsoft Education. I didn't know it, but there is a site called www.educationlabs.com, which is similar to the Office Labs innovation site, but specifically aimed at educational software and products for students and teachers. I might be working with these guys to see if we can collaborate to release Live Geometry as educational software for schools. That would be really cool!

    Semblio - digital learning from Microsoft

    Last, but not least, at the Productivity Science Fair I've met folks from Semblio, which is a really interesting product I didn't know about. Here's a quote (read more here):

    Now you can make your instructional materials even more valuable. Microsoft Semblio provides easy access to the power of Microsoft .NET and Windows Presentation Foundation (WPF) by tailoring the Microsoft development platform specifically to the education market. Get ready to create an immersive education content experience.

    Essentially, they leverage WPF to create rich interactive learning materials. We've met with the Semblio team and they were really excited to learn about Live Geometry. They were particularly happy that it's easy to create a WPF User Control hosting a geometry drawing and that I use XML as the serialization format, because this way it's super easy to integrate Live Geometry content with the Semblio framework.

  • Kirill Osenkov

    Calling new on an interface

    • 10 Comments

    Interesting thing: technically there is a way to call new on an interface to create an object. How? Using a feature in the C# compiler for COM-interop support:

    using System.Runtime.InteropServices;
    
    class Program
    {
        static void Main(string[] args)
        {
            IFoo foo = new IFoo();
        }
    }
    
    class Foo : IFoo
    {
    }
    
    [ComImport]
    [Guid("DC1CB768-0BE5-4200-8D0A-C844BFBE3DE7")]
    [CoClass(typeof(Foo))]
    interface IFoo
    {
    }

    Here you specify that Foo is a CoClass for the interface IFoo using the three attributes CoClass, ComImport and Guid. It does not matter that no real COM objects are involved, C# compiler is fine with that. What it does, it replaces the call to the IFoo() "constructor" to the equivalent constructor on the co-class Foo.

    Interestingly enough, Foo doesn't have to even implement IFoo - the program will compile just fine and it will create an instance of type Foo at runtime, but it will fail when we try to put an object of type Foo into a local variable of type IFoo.

    It's yet another way to instantiate a type without mentioning it in source code. As such, it can potentially be a way to achieve what factory methods do - instead of mentioning the concrete type in instantiations all over your code, you can just have a centralized place where you say what type to instantiate. With this you can easily substitute the concrete type via the CoClass attribute.

    However, this is not as powerful as factory methods (you have to recompile your app to change concrete class and you can't have multiple concrete types at the same time).

    I wouldn't encourage using this stuff anyway because this will probably confuse readers who read your source. But despite of anything, this *is* an interesting technique.

  • Kirill Osenkov

    Visual Studio disappears when creating a Silverlight 3 Application

    • 2 Comments

    I have Visual Studio 2008 SP1 and Silverlight 3 tools on the laptop I’m writing this post on. Ten minutes ago I was trying to create a new Silverlight 3 application through the New Project Dialog and after creating the project Visual Studio just disappeared on me.

    Usually when VS disappears instantly without the Watson dialog this means something really serious has happened, like a stack overflow, or an internal CLR exception.

    I was almost going to log in to work to get the symbols and sources and start debugging, but doing a web search beforehand turned out to be a good idea. Indeed – it turns out to be a known bug in the CLR execution engine, serious enough so that we even released a hotfix for it:

    You know that you’re seeing this issue if the Windows Application Error log contains the entry ID 1023:

    .NET Runtime version 2.0.50727.3053 - Fatal Execution Engine Error (6FC85E00) (80131506)

    Installing the hotfix 963676 from this location https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=16827 helped to resolve the problem.

    If you ran into this – sorry for the inconvenience!

  • Kirill Osenkov

    5 min. screencast: Live Geometry overview

    • 28 Comments

    Microsoft sponsored a usability study for my side project Live Geometry, and I have to say, it was awesome. It was a lot of fun watching the participants using the software and I got a ton of great and useful feedback.

    I have to confess, I didn’t realize that it’s not obvious how to use Live Geometry (especially if you’ve never seen it before). Since I was the one who developed the software, I subconsciously assumed that it’s all intiutive and trivial. Well guess what, it turns out to be not the case. I am not the end user. Things that are obvious for me, might not be obvious for others.

    So I developed a plan on how to make things better. There are two ways: improving User Experience and investing in User Education. The former will be a slow and gradual process of me designing the features and the UI, fixing bugs, reworking the UI and thinking through UI details.

    Today I’ll start approaching the task of User Education and present a 5 min. screencast – a brief overview of the Live Geometry software and its possibilities (Hint: double-click the video for fullscreen viewing):

    Get Microsoft Silverlight

    You can also download the .wmv file (15 MB).

    More documentation will follow later, but this should at least give a quick start and give you an idea of how things work.

    Any feedback is welcome!

  • Kirill Osenkov

    All C# Compiler Developer Team blogs

    • 2 Comments

    With Ian Halliday, a developer on the C# Compiler team who started to blog recently, all of the C# compiler devs are blogging! Here’s the list of their blogs sorted alphabetically:

  • Kirill Osenkov

    Instantiating types with no public constructors

    • 7 Comments

    It turns out, Activator.CreateInstance and Activator.CreateInstance<T> fail if there is no public parameterless constructor defined on a type we’re trying to instantiate. Even if the constructor is internal (basically, anything other than public), CreateInstance will fail. This one was a surprise actually, I would expect the reflection binder to work for internal constructors at least.

    Update: it turns out, there is an overload of Activator.CreateInstance(Type, bool) that does exactly what I want. Don’t use what I posted below :) Thanks to Andrey Shchekin for the tip!

    Nevertheless, a more powerful alternative to Activator.CreateInstance in this case is to find the non-public constructor and invoke it manually:

    using System;
    using System.Reflection;
    
    class Test
    {
        private Test() { }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
            var ctor = typeof(Test).GetConstructor(flags, null, new Type[0], null);
            var instance = ctor.Invoke(null);
    
            //var instance = Activator.CreateInstance<Test>(); // Exception: No parameterless constructor defined for this object.
            //var instance = Activator.CreateInstance(typeof(Test)); // Exception: No parameterless constructor defined for this object.
        }
    }

    Why do I need this? Well, there is a class in our codebase that everyone was instantiating all over the place. But this class should have inherently been a singleton. I changed the code all over the place to use a singleton instead of instantiating it and I wanted to prohibit people to instantiate this class in the future.

    We have a little Singleton helper that essentially looks like this:

    public class Singleton<T> where T : class
    {
        static T instance;
        public static T Instance
        { 
            get
            {
                if (instance == null)
                {
                    instance = Instantiate();
                }
                return instance;
            }
        }
    
        static T Instantiate()
        {
            return Activator.CreateInstance<T>();
        }
    }

    So I would just inherit the class that everyone was using from Singleton like this: CommonClass : Singleton<CommonClass> and make the constructor private so that people can’t instantiate it manually anymore. However this became a problem because the Singleton’s Instantiate() method failed for non-public constructors. Now that I’ve used the approach above, it works fine. Singleton can instantiate the class, but no one else can.

     

    P.S. Yes, I know about the right way to implement a singleton, I know about double-check locking and threading and that reflection is bad. But this solves the problem.

    P.P.S. Yes, I know about burning the base class and that mixing in a singleton via inheritance is generally a bad idea. It works for us and does it’s job.

    P.P.P.S. It occurred to me that if we had extension properties, one could have just made Instance an extension property on every type (that implements a certain “marker” interface). But there is no way currently to mix-in state into existing types (if you don’t look at WPF and their attached properties and dependency properties).

  • Kirill Osenkov

    Comparing doubles can produce unexpected results

    • 4 Comments

    Well, guess what, smart people learn from other people’s mistakes and Kirill learns from his own.

    This is actually a well-known caveat about doubles, but still a reminder about something to be aware of. A double value can be something else than you might think it is. For example, when you expect a double to be exactly 6, it could be 5.9999999999999991 and you will wonder, how on earth is it possible that 6 != 6:

    image

    The upper tooltip clearly shows that the second coordinate is 6, but comparing it with 6 fails. Whoa, the detailed view shows 5.9999999999999991.

    What’s up with that? Luckily, the .NET framework source is easily available, so a quick look at Point.ToString() reveals that they simply format the output to round away the last couple of precision digits. The X and Y on the contrary are displayed unformatted (or should I say formatted less aggressively).

    Under closer examination (and after half an hour of pulling my hair out) it looks like the system represented the calculation result as close to the decimal integer 6 it could, given the double precision in .NET encoded in binary. The failing code was comparing if (point.Y == 6) and the comparison failed against my expectations.

    The solutioin for this is to test for the fact, “is the value within epsilon of the ideal value of 6”, like this: if (Math.Abs(point.Y – 6) < 0.00000001) …

    I should have read more Eric back in school.

Page 4 of 7 (164 items) «23456»