May 2007 - Posts

My article about Extension methods is now on the web. Unfortunately an edit I made didn't make it into the print version (and the web version is the same as the print). The problem was as I looked at the way extension methods worked in Beta 1, it was as I was told it would work form discussions I had had with members of the VB team. But as I looked at it further it dawned on me that the design of having any instance method hiding all extension methods with the same name wasn't really desirable. So I talked to some folks on the VB team about this. Meanwhile we were pushing the deadline out for print. I ended up making edits but they didn't make it into the printed release.

The last two paragraphs of the article read:

If you recall the rules around precedence, you might be wondering if methods in your collection classes might Shadow LINQ statements by mistake. The answer to that is actually rather complex. The compiler goes out of its way to let the LINQ statements work. If you add a Select method to your collection class, VB uses AsQueriable to cast your collection to an IQueriable type, which means the compile precedence is on the IQueriable type. If you also have an AsQueriable type, it tries an AsIEnumerable extension, and failing that, it tries the Cast extension method. If all of those are Shadowed then the compiler throws a compile time error.

The goal is to allow you to use LINQ statements on existing collections of all sorts. Methods inside the collection classes are viewed as being from prior to LINQ and hence having a different intent. For this reason, the compiler attempts to navigate around them. If you need to change the LINQ behavior, you must use extension methods defined in a module and implement namespace precedence to suit your needs.

That was technically correct at the time, but I believe inaccurate as to what should happen, and as to what happens in C#. The edited article replaced those two paragraphs with the following:

If you recall the rules around precedence, you might be wondering if methods in your collection classes might Shadow LINQ statements. The answer to that is instance methods will shadow by name and signature any extension methods. In the March CTP VB behaves differently: See sidebar "Out of the Shadows".

Shadowing by name and signature in this case means methods that would resolve to the same if both were instance methods. Remember extensions are Shared methods with the first parameter the instance: hence when determining if a method is shadowed by an instance method, the first parameter in the extension method is removed from the actual signature.

For example, a Select extension would be shadowed by an instance method as long as the instance method has the correct and matching signature.

 

' inside a module

<Extension()> _

Public Function [Select](Of TSource, TResult) _

        (ByVal source As IEnumerable(Of TSource), _

        ByVal selector As Func(Of TSource, TResult)) _

        As IEnumerable(Of TResult)

        ….

End Function

 

 

' instance method inside the collection class

Public Function [Select](Of TResult)_

        (ByVal selector As Func(Of T, TResult)) _

        As IEnumerable(Of TResult)

        ….

End Function

 

The source parameter is removed from the signature for the extension method, generic parameters are resolved, and return types ignored to determine if the instance method shadows the extension: if they match, the instance method gets precedence.

 

The difficulty in using instance methods over extension methods for LINQ queries is you need to chain return types with types you have your instance methods in. Taking the earlier example of selecting a distinct list, the Distinct method has to be inside the type returned by the Select method. In that particular example you can have the Select return the same collection class and put your Distinct method in there. This becomes more complex when dealing with other projections and anonymous types. Rather than use instance methods you'll find it generally easier to import a module with your extension methods in it.

 

Extension methods can make creating customized LINQ queries, easier, and easier to share amongst your different libraries or collection classes. Powerful, yet incredibly simple in essence: used wisely they'll make your coding easier.

 

 

The sidebar was :

Out of the Shadows

In the March Orcas CTP, and most likely for Beta 1 of Orcas, VB shadows all extension methods by an instance method with the same name. That is, it shadows by name, not by name and signature. This has some unfortunate side effects such as the inability to add extensions with more or different parameters. A more complex issue arises around LINQ queries: if you have a Select method in your collection class that is the incorrect signature for the LINQ query, any Select extension in scope will be ignored for your collection class because they are shadowed. The compiler will then call a different extension method AsQueriable to cast the type to an IQueriable(Of T). Extension methods are then resolved for an IQueriable(Of t) rather than your collection class type. If your Select extension was written strongly typed to your collection class, it won't get called.

 

The good news is I've had a chat to some of the VB team, and they've promised me they'll look into. Most likely they will change it to shadows by name and signature. The bad news this change won't make it into Beta 1, you'll have to wait till Beta 2.

 

This highlights why we need to look at the early CTP's and betas and give Microsoft feedback. They share these early bits with us so as we can shine light on things others might not notice and give them feedback early enough to steer them clear of any rocks lurking in the shadows. J

 

And a special thanks to Adrian and Amanda for listening J

 

My sincerest apologies for not getting this in the article on time to make the print release.

with no comments
Filed under: , ,

Earlier today I noticed a comment from Tim Ng on my early blog about mutable anonymous types. It was one of those comments that just felt wrong.... the more I thought about this the more I realised just how wrong it is.

To allow for mutable and immutable anonymous types, Paul Vick indicated VB will introduce a Key keyword to be used inside the With declaration,, e.g.

Dim customer As New With {Key .Id = 1, .Name = "Fred"}

Now theoretically this will give you a class with this signature:

Class Foo

    Sub New(ByVal id As Int32)
        Me.m_ID = id
    End Sub

    Private m_ID As Int32
    Private m_Name As String

    Public ReadOnly Property ID() As Int32
        Get
            Return m_ID
        End Get
    End Property

    Public Property Name() As String
        Get
            Return m_Name
        End Get
        Set(ByVal value As String)
            m_Name = value
        End Set
    End Property

 End Class

I've omitted some of the details such as GetHashCode and Equals etc. Now if I was to try to write the same code with Foo instead of the anonymous type the code would fail.

Dim customer As New Foo With {Key .Id = 1, .Name = "Fred"}

Instead I have to use the only constructor and I can't set Id, and I can't set Id to be a key. The only valid syntax is:

Dim customer As New Foo(id) With { .Name = "Fred"}

So in reality we already have ways to work with readonly Properties that are only settable via a constructor. The With {} syntax also disallows setting ReadOnly properties, in fact in the above example intellisense will only display the Name property for Foo, which is all as it should be. But for some reason, one I have yet to fathom, the VB team has decided to allow you to set a ReadOnly property if you preference it with the new Key keyword.

Personally I think the syntax should be the same, be it anonymous types or existing types :

Dim customer As New Foo(id) With { .Name = "Fred"}

and

Dim customer As New(id) With { .Name = "Fred"}

   

  

If you're using Windows Vista and are unable to add a web folder (http network location), and you're getting error message like :

"The folder you entered does not appear to be valid. Please choose another."

Then try downloading an installing this update for WebDAV from Microsoft. It worked for me J

with 9 comment(s)
Filed under:

Paul Vick posted that anonymous types will remain mutable in VB. Generally this looks good, I just hope that it is not a requirement to specify the key. That is if no key is specified, then the hashcode will be generated will be created based on all the fields. One thing that struck me though was in Sree's post about anonymous types being immutable in C# he mentioned threading :
it drastically simplifies the code that uses the object since they can only be assigned values when created and then just used (think threading).

This got me thinking... Given the scope of anonymous types in C# it's not like you could use traditional threading anyway, as they are pretty much limited to within a procedure.. at least as far as the threading you control is concerned. But if you start thinking about iterators, expression trees, delayed evaluation, multi processors, the realization that threading is something that might happen at a different level if everything else falls into place should occur to you. That is, if you set everything up nicely, smart iterators may be able to decide on using multiple threads or not. Ideally this is something we shouldn't have to worry about, but realistically if you want that to work you probably will need to limit your demands. Asking it to do locks and synchronisation on mutable types probably is asking that little bit too much.

The other benefit of having an immutable type is of course the design time experience is explicit that fields are read-only.

VB will of course allow you to create anonymous types that are immutable, mutable or partially mutable. Essentially, you make any property as being readonly by specifying Key before the property name. For example:

Dim projection = From c in Countries Select New With { Key .Country = c.Country, Key .State = c.State }

The short syntax:

Dim projection = From c in Countries Select c.Country, c.State

Will how be a mutable type, the long explicit syntax you can decide which fields are mutable and which are not.

I wonder if it would be more VB'ish to include a modifier for the entire projection. If you start thinking about nested projections etc, it would get difficult to check to see that every member is specified only via the Key.XXX syntax, and hence hard to ensure if the type is immutable. I kind of think it might be nice to be able to write :

Dim projection = From c In Countries Select c.Country, c.State For ReadOnly

 

 

with 2 comment(s)
Filed under: , ,

I've only been seriously on Vista for a week or so, but so far I have found many frustrations, thankfully I've managed to work around.

  1. They removed the ability to mark a file type as "Prompt to download". You use to get to this via file associations, now you need to use the registry.
  2. I had all sorts of weird problems in Internet Explorer around using Microsoft's download tool, or reading blogs etc. Turned out the problem was I moved my %temp% path, and internet explorer couldn't write to the Low directory in that until I marked the directory as having low permissions:
    icacls %temp%\Low /setintegritylevel LOW(OI)(CI)
    That fixed the problem. Even looking tat that now, and given there was no error message from IE, I'm really amazed I got that one solved ;)
  3. I went to open a PPT deck today and couldn't open it in Vista with PowerPoint 2007. On my XP PS2 machine using PowerPoint 2007 I could. The error message in Vista was it couldn't find some printer, yet I deliberately have my print spooler stopped in XP and in Vista. Manually starting it when needed. Well for some reason in Vista I needed to manual start the print spooler, yet in XP I didn't.
with 1 comment(s)
Filed under:

 

Just as some bloggers harp over the delays in the entity framework, talking about object spaces, etc, the ADO.NET team released today Jasper.

<quote>

Jasper leverages the power of dynamic languages and the concept of convention over configuration to provide a programming surface for data that enables rapid development of data-bound applications. While most other rapid data access frameworks are only capable of working against simple databases, Jasper can scale to almost any database, regardless of size or complexity. This is possible because Jasper takes advantage of the ADO.NET Entity Framework's significant investments in mapping and conceptual data modeling.

</quote>

 

How sweet it is J

 

with no comments
Filed under: , ,

The goodies from MIX are now starting to pour into Microsoft's servers.... Silverlight SDK being just one

with no comments
Filed under: ,