Showing posts with label .Net 4. Show all posts
Showing posts with label .Net 4. Show all posts

Wednesday, February 20, 2013

Crazy reference leakage using extension methods and generics

It appears that if you have an extension method, that is in-scope (i.e. namespace included), even if you don't use it you have to reference all the assemblies that are part of the generic type constraint.

This kinda sucks.

Normally if you use a type from another assembly, and that type has as part of its interface another type in another assembly, you have to reference both assembly. Fine. But only if you use it.

eg: if you reference assembly 'Animal' and use a class 'Cow' that has a property 'Color', and the type of Color is defined somewhere else (System.Windows.Forms) you have to reference that too. But if you get the cow via the IBovine interface, and that doesn't expose Color, you don't need the reference (at least not statically).

If, however, in the same namespace, there's an extension method that you're not using, and that extension method has some type constraints, you have to reference all the assemblies for all the type constraint parameters.

For example, if you put this in one assembly, in a namespace you merely import:


  public static class NotUsed{
        public static void DefinatelyNotUsed(this TContext context, Action thing)
            where TContext : DataContext
        {
            
        }
  }
... then you'll also have to pull in System.Data.Linq to get the 'importing' assembly to compile.

Doesn't this strike you as odd? I'm sure I can hear a gestalt Eric Lippert in my head explaining why, but I was certainly surprised.

Tuesday, January 08, 2013

The Windows RT desktop. For why?

I still don't understand Windows 8 RT (aka Microsoft Surface, aka Windows on Arm), or more specifically it's desktop mode.

On Windows 8 Pro (the x86 version) it all makes sense: desktop mode opens the door to all the 'legacy' apps you know and love, whilst the device itself weans you onto the world of RT/store apps. As an enterprise developer you can target either, most likely running existing corporate apps on the desktop whilst mulling the trade-offs (and $) involved in rewriting the front end to target Metro.

But on Arm it's crippled: running only Microsoft-sanctioned apps (Office, Notepad and explorer) without jailbreaking. Why?

Clearly you can't expect it to run existing x86 apps, but for enterprise developers working in .Net this is a slap in the face. You're barred from running existing .net 4 desktop apps on the Surface RT desktop, and you can't build desktop apps using the Win RT runtime either.

This is a crazy situation that smacks of half-baked.

If the desktop mode on Arm is useful - and I'd argue it is - it should be possible for more than just Microsoft to write for it. Ideally enterprises could run existing .Net apps unmodified, but there's clearly advantages (re: capability, performance and battery life) in encouraging them to embrace the Win RT APIs.

Conversely if the desktop mode is redundant, Microsoft need to seriously pull their finger out replicating all that functionality in the Metro interface, including a Metro version.

I would like for the former to be the case. I suspect Microsoft's roadmap is the latter, that the desktop's just there till Office gets ported proper. Whichever way, we have a ridiculous situation where if an enterprise developer wants to target Windows 7 and both Windows 8's they have to ... write a web app. Way-to-go Microsoft![1]

I keenly await Xamarin's Mono-Surface[2], which will let you run .Net apps on the Microsoft Platform. Now that would be progress.


[1] Sure they gave the enterprise the finger with the phone too. I guess we shouldn't be surprised. But perhaps this is just Sinofsky's 'my way or the high way' showing through
[2] This is a fictitious product, and any resemblance to actual products planned or otherwise is entirely coincidental

Wednesday, September 08, 2010

.Net 4 not supported on Windows 2008 Server Core

There is an explanation from the .net SKU owner as to why (which I don’t entirely follow), but the bottom line is that what the download page says is right – it’s just not available. So no Distributed Cache either.

Poo.

(It does support a subset of the net 3.5 functionality, largely orientated towards ASP.Net support – there’s a basic explanation of which bits here)

Friday, June 11, 2010

Converting to Int

You wouldn’t have thought that such as basic operation as turning a double into an integer would be so poorly understood, but it is. There are three basic approaches in .Net:

  • Explicit casting, i.e. (int)x
  • Format, using String.Format, or x.ToString(formatString)
  • Convert.ToInt32

What’s critical to realise is that all of these do different things:

    var testCases = new[] {0.4, 0.5, 0.51, 1.4, 1.5, 1.51};

    Console.WriteLine("Input  Cast   {0:0}  Convert.ToInt32");

    foreach (var testCase in testCases)

    {

        Console.WriteLine("{0,5} {1,5} {2,5:0} {3,5}", testCase, (int)testCase, testCase, Convert.ToInt32(testCase));

    }

Input  Cast   {0:0} Convert.ToInt32
0.4 0 0 0
0.5 0 1 0
0.51 0 1 1
1.4 1 1 1
1.5 1 2 2
1.51 1 2 2


As my basic test above shows, just casting is the equivalent of Math.Floor – it looses the fraction. This surprises some people.



But look again at the results for 0.5 and 1.5. Using a format string rounds up[1], to 1 and 2, whereas using Convert.ToInt32 performs bankers rounding[2] (rounds to even) to 0 and 2. This surprises a lot of people, and you’d be forgiven for missing it in the doco (here vs. here):



Even more interesting is that PowerShell is different, in that the [int] cast in PowerShell is the same as a Convert.Int32, not a Math.Floor():



> $testCases = 0.4,0.5,0.51,1.4,1.5,1.51
> $testCases | % { "{0,5} {1,5} {2,5:0} {3,5}" -f $_,[int]$_,$_,[Convert]::ToInt32($_) }

Input Cast {0:0} Convert.ToInt32
0.4 0 0 0
0.5 0 1 0
0.51 1 1 1
1.4 1 1 1
1.5 2 2 2
1.51 2 2 2


This is a great gotcha, since normally I’d use PowerShell to test this kind of behaviour, and I’d have seen the wrong thing (note to self: use LinqPad more)



 



[1] More precisely it rounds away from zero, since negative numbers round to the larger negative number.



[2] According to Wikipedia bankers rounding is a bit of a misnomer for ‘round to even’, and even the MSDN doco on Math.Round seems to have stopped using the term.

Tuesday, April 13, 2010

3 Reasons to Avoid Automatic Properties

That’s dramatic overstatement of course, because automatic properties are great in many cases (though are public fields really so wrong?) But now that VB.Net has joined the party too [1], it’s worth remembering that they are not all good news:

1/ They Can’t be Made ReadOnly

Sure you can make them have a private setter, but that’s not the same as a readonly field, which is a great check against whole classes of screw-ups. If a field shouldn’t change during an instance lifetime, make it readonly, and save yourself some pain.

2/ No Field Initializers (in C#)

The nice thing about initializing fields in the field initializers is you can’t forget to do so in one of the constructor overloads, and (in conjunction with readonly fields) you can ensure it can never be null. Since this is all on one line it’s easy to inspect visually, without having to chase down code paths / constructor chains by eye.

(You can vote for this, for all the good it will do [2])

3/ Poor Debugging Experience

Properties are methods, right, even auto-generated ones, and need to be executed for the debugger to ‘see’ the value. But that’s not always possible. If the managed thread is suspended (either via a threading / async wait, or by entering unmanaged code) then the debugger can’t execute the property at all, and you’ll just see errors the below:

Cannot evaluate expression because the current thread is in a sleep, wait or join

Here you can only determine the value of ‘AutoProperty’ through inference and guesswork, whereas ‘ManualProperty’ can always be determined from the backing field. This can be a real pain in the arse, so it’s worth avoiding automatic properties for code around thread synchronisation regions.

As an aside remember that there are backing fields, it’s just you didn’t create them, the compiler did, and it used it’s own naming convention (to avoid collisions) which is a bit odd. So if you write any ‘looping over fields’ diagnostic code you will see some strange names, which might take some getting used to. You’ll also see those in WinDBG and CDB when you’re looking at crash dumps and the like.

 

[1] ...but I bet the VB community spat chips over the curly brackets in Collection Initializers
[2] And yet whilst VB.Net 4 has this, they don’t have mixed accessibility for auto properties yet. Go figure.

Monday, March 22, 2010

3 Races with .Net Events

I didn’t even know about #3 till recently, so time for a quick recap:

Race Between Null Check and Invocation

Since an event with no subscribers appears as a ‘null’, you have to check the event has been wired before you call it, right. Which typically is done like this:

	// post an event
if(ThingChanged != null)
ThingChanged(this, args);


This is the wrong way of doing it. In a multi-threaded environment the last subscriber to the event might unsubscribe between the null check and the invocation, causing a null reference exception:



	// post an event
if(ThingChanged != null)
// other thread unsubsubscribes here
// next line now causes null ref exception
ThingChanged(this, args);


Despite the MSDN guidance [1], this is a very, very common mistake to make. I found one the first place I looked (a CodePlex project), and also in the ‘overview’ page for the guidance above :-(. And most of the time you get away with it just fine: limited (if any) concurrency and a tendency to wire events 'for life' means it's very unlikely to happen. But as you ramp up the parallelism, and start hooking and unhooking events dynamically during execution, this will eventually bite you.



The easy fix is to cache the delegate locally first:



    var handlers = ThingChanged;
if (handlers != null)
handlers(this, args);


(I usually distribute this as a snippet to attempt to make sure people on my team do this automatically, as it’s easy to fall back on bad habits. The snippet also sets this up as a ‘protected virtual OnThingChanged’ method, uses EventHandler<T> and generally tries to encourage correct usage. ReSharper can also generate the correct usage for you)



These days you can ‘wrap up’ the pattern above as an extension method, but it’s not as flexible as actually just creating a member. You don’t have anywhere to put specific pre-event raising logic, and derived classes can’t override OnThingChanged to do their own thing first (something many UI controls and WebForms pages do a lot of).



Finally you can use the field initializer for the event to assign an empty delegate, and prevent the event field from ever being null. This isn’t actually my preference, but it is quite neat:



	public event EventHandler<EventArgs<Thing>> ThingChanged = delegate{};

// invoking the event then never needs the null check:
ThingChanged(this, args);


I don’t like the idea of a wasted empty delegate call, but I’m just fussy.



Delivery of Event to Stale Subscriber



Unfortunately the pattern above appears to trade one race condition for another, since now the event list that’s invoked is cached (and hence stale). A subscriber can unsubscribe but still subsequently receive an event if the deregistration occurs after the list is cached.



This has been discussed at length on StackOverflow, and on Eric Lippert’s blog, but the salient detail here is that this is unavoidable. The same race occurs if a subscriber unsubscribes during traversal of the event invocation list, but before that subscriber has been notified, or even between taking a reference to an item in the list and invoking it. So even the ‘empty delegate’ version has the same issue.



Eric says:




“event handlers are required to be robust in the face of being called even after the event has been unsubscribed”




…i.e. check your internal state, and act accordingly. In particular, for IDisposable classes, this means that you should not throw an ObjectDisposedException from your event handlers, even if you are disposed. Just don’t do anything.



It is a pity that this requirement is not more widely socialized than just his blog :-(



Race Condition on Event Assignments Within Declaring Class



I had no idea about this until recently when Chris Burrows started updating his blog again, but whilst event assignments are normally ‘thread safe’ (synchronised during the += / –= to avoid races on updating the (immutable) delegate list in-place), referencing the event from within the declaring class doesn’t bind to the event, it binds to the underlying private delegate. And there’s no automatic compiler voodoo synchronisation going on for you when you add and remove things from that.



If you are doing this you must lock on something, and to maintain consistency with the compiler-generated protection for the public event field, you have to lock(this). But again this will only be an issue if multiple threads are (un)subscribing simultaneously anyway, so if your in-class event hook up is in your ctor, before your ‘this’ reference got leaked or you spun off a background worker, you are safe as-is (I think).



For .Net 4 this issue has been fixed: using the += / –= syntax binds to the compiler-generated thread-safe assignment whether you are in the class or not. You can still do unsafe things with the private field if you start explicitly using Delegate.Combine, but that’s just weird anyway.



What’s nice here is the fix was part of removing the locking altogether. Now updates to events occur via a Interlocked.CompareExchange[1] spin, which is a classic no-lock approach:



public void add_Something(EventHandler value)
{
EventHandler handler2;
EventHandler something = this.Something;
do
{
handler2 = something;
EventHandler handler3 = (EventHandler) Delegate.Combine(handler2, value);
something = Interlocked.CompareExchange<eventhandler>(ref this.Something, handler3, handler2);
}
while (something != handler2);
}


This is actually a pretty good pattern to copy if you are targeting very high parallelism, because these atomic compare-and-swap operations are considerably faster than Monitor.Enter (which is what lock() does), so it’s nice to see a good ‘reference’ implementation to crib off (and one that will be pretty ubiquitous too).



Bonus: Robust Event Delivery



Nothing to do with race conditions per-se, but sometimes a subscriber to your event will throw an exception, and by default this will prevent all the subsequent subscribers from receiving the notification. This can be a real swine to diagnose sometimes, especially as the order of event invocation isn’t something you have any control over (strictly speaking it’s non-deterministic, however it always appears to be FIFO in my experience).



Anyway, if you want robust event delivery you should broadcast the event yourself, in a loop, collect the exceptions as you go and raise some kind of MultipleExceptionsException at the end:



    protected virtual void OnSomething(EventArgs e)
{
var handlers = Something;
if (handlers != null)
{
var exceptions = new List<Exception>();
foreach (EventHandler handler in handlers.GetInvocationList())
{
try
{
handler(this, e);
}
catch (Exception err)
{
exceptions.Add(err);
}
}
if (exceptions.Count > 0)
throw new MultipleExceptionsException(exceptions);
}
}


At this point the extension method approach beckons because this just blew right out.



Bonus: Lifetime Promotion Via Event Registration



Remember that subscribing to an event is giving someone a reference to you, i.e. an extra root that can prevent garbage collection. You are tying your lifetime to that of the objects that you are listening to.



Typically this isn’t a problem, because the publisher is a more short lived object than the subscriber, but if the publisher sticks around a while (or for ever, if its a static event) it’s very important that subscribers unsubscribe themselves when they are done or they will never get GC’d.

Monday, November 30, 2009

Bugs, Betas and Go-Live Licences

.Net 4 and Visual Studio 2010 are currently available in Beta 2, with a Go-Live licence. So now’s a great time to download them, play with the new features, and raise Connect issues about the bugs you find, right?

Wrong.

These products are done. Baked. Finished[1]. It’s sad, but true, that generally by the time you start experimenting with a beta it’s already too late to get the bugs fixed. Raise all the Connect issues you want: your pet fix may make it into 2013 if you are lucky. Eric Lippert put it pretty well recently:

FYI, C# 4 is DONE. We are only making a few last-minute "user is electrocuted"-grade bug fixes, mostly based on your excellent feedback from the betas. (If you have bug reports from the beta, please keep sending them, but odds are good they won't get fixed for the initial release.)

Sadly, if you are playing with the betas, you are better off making mental notes of how to avoid what problems you do find, or praying any serious ones already got fixed / are getting fixed right now (eg: performance, help, blurry text, etc…)

 

[1] I’m exaggerating to make a point here, and please don’t think I have an inside track on this stuff, because I don’t.

Popular Posts