Subscribe: The Monkey's Grinder
http://themonkeysgrinder.blogspot.com/feeds/posts/default
Added By: Feedage Forager Feedage Grade B rated
Language: English
Tags:
code  foo  generic variance  generic  implementation  interface  method  new  null  object  public  string  thing  variance  void 
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: The Monkey's Grinder

The Monkey's Grinder





Updated: 2015-09-16T10:39:30.833-07:00

 



Disoriented

2010-08-12T12:29:46.550-07:00

The Tyranny of Terminology would have us discussing Object Orientation and Functional Programming, calling our code by its Patterns and Paradigms. I am going to plead ignorance of these epistemologies and just show you some C#. Feel free to know for yourself what it Really Means.Code like this was written for Mono.Upnp. Expect news there soon.Our story begins here:abstract class ContentDirectory"ContentDirectory" is UPnP parlance for a directory of content. (See the ContentDirectory:1 service template PDF. Or better still, don't.) The CD is a hierarchy of objects. Objects have descriptive class names like "object.item.audioItem.musicTrack" and "object.container.systemFolder". That gives you some idea, yes?The CD has methods like Browse and Search. Here is the signature for Search:string Search (string containerId,               string searchCriteria,               int startIndex,               int requestCount,               out int numberedReturned,               out int totalMatches)I will pause to explain the return value: it is a string of XML describing the result set.Now, in a source file not far away...class InMemoryContentDirectory : ContentDirectoryIt may not shock you to learn that an InMemoryContentDirectory keeps an in-memory collection of its object hierarchy. It has a method called GetChildren. Here is the signature:IEnumerable GetChildren (string containerId)Explanatory pause #2: CDObject is short for "Content Directory Object"; it is the root type of objects in the CD.If you were me, then this is how you would implement InMemoryContentDirectory.Search:totalMatches = 0;var results = new List (requestCount);foreach (var child in GetChildren (containerId)) {    if (IsMatch (child, searchCriteria)) {        totalMatches++;        if (totalMatches > startIndex &&            results.Count < requestCount)        {            results.Add (child);        }    }}numberReturned = results.Count;return Serialize (results);I may or may not have promised a theory-free post — I don't really remember now — but in any event, this is standard Object Oriented Programing fare. To state the obvious:You create a list to hold the results.You iterate through the children of the subject container.For each match, you increment totalMatches.If you have not reached the startIndex, you keep going.Otherwise unless you have reached the requestCount, you add the matching object to the results list.You return the serialized results list. Which iterates through the list and serializes each object to XML, returning the whole XML string.I have highlighted the problems with your solution in salmon. You are allocating a new List to hold objects which already exist in a collection somewhere. Also, you are iterating through the results twice: first in your pass through the container's children and then again to serialize them.If you were still me then this just won't do. LINQ should come to mind but have I got a fun surprise for you: Mono.Upnp targets the .NET 2.0 profile. So how might you Query the Language without fancy INtegration?IEnumerable Search (    string containerId,    string searchCriteria,    int startIndex,    int requestCount){    var count = 0;    foreach (var child in GetChildren (containerId)) {        [...]



Mono.Upnp Dance Party

2009-07-28T20:34:44.434-07:00

So it's been a while since mention was made of a certain UPnP library. What happened? First, I had various other things to do. Second, I decided to do two or three major refactorings, ditching a lot of code. Third, I moved development to github.

What the status?
The status? The status, you ask?! THIS is the status! If you can't see, I am pointing at my TV. My TV which is connected to my PS3. My PS3 which is playing music from my laptop computer with WIRELESS NETWORKING! Yes friends, tonight at last, Mono.Upnp and the PS3 are doing the DANCE OF LOVE. I plug, it plays. Universally. About ten minutes ago I finally tracked down the typo responsible for a day's worth of debugging and let me tell you, Starfucker never sounded so good (and they already sound so good anyway, seriously, you should listen to them).

What now?
I've kept pretty quite about the whole project because I wanted to lay all the groundwork before make too much noise. There is still work to be done on the core of the library, but now that it's working I'll start sharing more frequent updates. You can follow the project on github if you want commit-by-commit news.

Can I help?
Sure! But helping might be a little tricky. The solution only loads in MonoDevelop SVN, and there are certain necessary BCL fixes that require Mono from SVN too (one of them isn't even committed yet). It's not quite "checkout, compile, run," but if you're interested in helping out, I will be more than happy to get you up to speed. I wrote a TODO on the github wiki today with some stuff that needs doing. Testing is also something I will need help on. I don't have access to an XBox 360 anymore, so I'm going to need help on that front. As the library and the tools evolve, we'll need to test with as many devices as we can.

Yeah!
Yeah indeed! NOW DANCE!



C#er

2009-11-08T00:24:37.116-08:00

Was chillin' with the impish abock last weekend when, all of a hullabaloo, he geniused something wonderful."Behold!" he cried:var button = new Button {    Label = "Push Me",    Relief = ReliefStyle.None};button.Clicked += (o, a) => Console.WriteLine ("ouch!');To which I replied, "?""Watch..." said he:var button = new Button {    Label = "Push Me",    Relief = ReliefStyle.None,    Clicked +=> Console.WriteLine ("ouch!")};"?!" came my response."Is not it better?""Yes," quoth I, "but gentle abock, this wundercode... it doth not compile!""... YET!"Well friends, yet is over. I am here today to tell you that yes, IT DOTH COMPILE. This is what you get when Scott forgets to pull the git repos for his real projects before a plane flight: unsolicited language features. And there are other goodies:As with anonymous methods via the delegate keyword, you may omit the parameters to a lambda if you aren't going to use them. This is also helpful when the delegate type has no parameters. For example:Func myFunc = () => "blarg";Just look at those parenthesis! Chillin' there all higgledy piggledy. They look like some unseemly ASCII art. But now, presto chango:Func myFunc => "blarg";See what I did there? That's called an assignment arrow. It is better. Don't argue with me, because you're wrong.For my next trick, you can do the same kind of thing with lambdas and event handler registration.myButton.Clicked +=> Console.WriteLine ("higgledy piggledy");Because who ever uses the EventHandler arguments? A big, fat nobody, that's who.Last but not least, you can now do all of this plus regular event handler registration inside of object initializers. abocks around the world rejoice!There Is No Syntax Without Corner CasesSo there is at least one possible ambiguity with this new syntax:class Foo {    public void Add (Action action) { ... }    public Action Bar { get; set; }}// Meanwhile, in some unsuspecting method:var foo = new Foo {    Bar => Console.WriteLine ("HELP ME!")};Question: Is that an object initialization, or a collection initialization?Answer: It's ambiguous.Solution: It's an object initialization. If you want it to be a collection initialization, throw some parenthesis around "Bar." This would be a good candidate for a compiler warning. And if you want to make it an unambiguous object initialization, you could do:var foo = new Foo {    Bar = () => Console.WriteLine (        "What does this ASCII art even mean?") };PatchThe patch for all of this is available here. Apply to mcs, recompile, then use gmcs.exe passing -langversion:future.FutureThere has been on-again-off-again talk about adding non-standard language features to the C# compiler under the guard of -langversion:future. The main concern voiced is the ability to maintain such extensions. I will definitely discuss this patch with Marek and co. to see about landing it in mainline. I'll keep you up to date.Are You Bock Enough?In the meantime, I call upon manly man Aaron Bockover to make the only manly choice available: fork C# and ship the compiler. Because you're not really a serious media player until you have your own special language.[...]



Casting Call

2009-07-17T07:57:02.336-07:00

Type safety only gets you so far; eventually you have to cast. There are three features in the C# language which address typing: the unary cast operator and the binary "as" and "is" operators. I see people misuse these operators all the time, so here for your records are the official Best Ways to use each.

If you want to check the type of an object and do not care about using the object as that type, use the "is" operator. For example:

if (thing is MyType) {
    // do something which doesn't involve thing
}

If you want to check the type of an object and then use that object as that type, use the "as" operator and the check for null. For example:

var my_type_thing = thing as MyType;
if (my_type_thing != null) {
    // do something with my_type_thing
}

This only works for reference types since value types cannot be null. For value types, use the "is" and cast operators. For example:

if (thing is MyValueType) {
    var my_value_type_thing = (MyValueType)thing;
    // do something with my_value_type_thing
}

If you know for a fact that an object is some type, use the cast operator. For example:

var my_type_thing = (MyType)thing;
// do something with my_type_thing

These patterns minimize the operations performed by the runtime. This wisdom comes by way Marek who educated me on this a while ago. Please pass it on.



Dear LazyMarket

2009-07-09T14:27:56.474-07:00

Are you hiring? Do you know someone who is hiring? Well you're in luck! Because none other than yours truly is looking for a job. If you're interested in how great I am, send an email to lunchtimemama@gmail.com and I'll get you a copy of my resume. I look forward to hearing from you...



Variance, Thy Name is Ambiguity

2009-06-30T23:51:39.236-07:00

PreviouslyOn This Blog..."I love you, Generic Variance, and I want your babies RIGHT NOW!""I think there's something you should know about Generic Variance...""I can change him!"And now, the thrilling continuation...I've just sent my recommendation to the ECMA 335 committee regarding the generic variance problem. I present it here for your reading pleasure:Quick RecapThe following is an example of an ambiguous circumstance involving generic variance, the very sort over which we have all lost so much sleep:.class interface abstract I<+T> {    .method public abstract virtual instance !T Foo ()}.class A {}.class B extends A {}.class C extends A {}.class X implements I, I {    .method virtual instance class B I[B].Foo () { .override I::Foo }    .method virtual instance class C I[C].Foo () { .override I::Foo }}// Meanwhile, in some unsuspecting method...I i = new X ();A a = i.Foo (); // AMBIGUITY!Give a Runtime A BoneTo disambiguate such situations, we introduce a new custom attribute in the BCL. For the sake of example, let's call it System.PreferredImplementationAttribute. The PreferredImplementationAttribute is applied to a type and indicates which implementation should be selected by the runtime to resolve variance ambiguities. Our above definition of the type X would now look like this:.class X implements I, I {    .custom instance void System.PreferredImplementationAttribute::.ctor (class System.Type) = { type(I) }    .method virtual instance class B I[B].Foo () { .override I::Foo }    .method virtual instance class C I[C].Foo () { .override I::Foo }}New RulesWith the addition of this attribute, the runtime requires that any type defined in an assembly targeting the 335 5th edition runtime which implements multiple interfaces that are variants of a common generic interface MUST specify ONE AND ONLY ONE PerferredImplementationAttribute for EACH of the potentially ambiguous common interfaces, and that each such specification of a PerferredImplementationAttribute must reference an interface implemented by the type that is a legal variant of the ambiguous common interface. In other words, all possible ambiguities MUST be disambiguated by the use of PreferredImplementationAttribute custom attributes. If a type does not satisfy these rules, the runtime MUST throw a System.TypeLoadException.As this rule only applies to assemblies targeting the new version of the runtime, old images will continue to execute without issue. If the committee prefers, the resolution of ambiguities in old types may remain unspecified, or alphabetical priority could be codified in the spec to standardize such behavior. I would be fine leaving it unspecified.Custom Attributes vs. MetadataIdeally, I feel disambiguation information belongs in the type metadata structure rather than a custom attribute. If the committee feels that amending the metadata specification is tenable, I would recommend doing so (though I don't have any thoughts at this time on the exact logical or physical nature of such an amendment). If, on the other hand, changing the metadata spec at this point in the game is not feasible, then a custom attribute will just have to do. I see the addition of one custom attribute type to the Base Class Library as entirely justified.An Aside to Our Friends on the 334 CommitteeAs a note to language designers targeting the runtime, I personally would consider it obnoxious if developers where burdened with the manual application of such a custom attribute. C# and other languages would do well to prohibit the direct use of the custom attribute, favoring instead a special syntax to denote the preferred implementation (the "default" keyword comes to mind in the case of C#). If this[...]



Further Generic Variance Thoughts

2009-05-17T09:39:22.096-07:00

I was writing a type today that implements both IDictionary and ICollection. These interfaces require the implementation of both IEnumerable and IEnumerable>. In .NET 4, the IEnumerable type will be covariant. This exposes my type to potential ambiguity if it is assigned to a location of type IEnumerable (see the previous post for details). If I were to follow my own advice and forbid the implementation of multiple interfaces which are variants of a single common interface, this type would be illegal. So on further reflection, I have decided to amend my opinion thusly: If there are multiple interface implementations which are variants of a common interface, then there must be implicit implementations of all of the potentially ambiguous members. These public members are then selected by the runtime to satisfy otherwise ambiguous calls. The implicit member implementations need not all be for the same interface. For example, if we have some interface IFoo with members T Bar(); and T Bat(); and we have some type with implements both IFoo and IFoo, it could have the members public string Bar(){} and public Uri Bat(){}. Any call to IFoo.Bar() on an object of this type will execute the IFoo implementation, and IFoo.Bat() will execute the Uri implementation.

I believe that this restriction should be enforced at least at the language level (for all variant-capable languages targeting .NET), if not at the runtime level: all potentially ambiguous members must have public implementations. This resolves the ambiguity in a logical way, allows for more complex type design (which, as in the case of my type today, is desirable), and gives developers the ability to control which implementation will be selected. I think it is a Good Thing.



Who's Afraid of Generic Variance?

2009-05-06T14:35:44.707-07:00

AbstractThis post is an in-depth exploration of generic variance in the ECMA 335 standard and the REALLY BIG PROBLEM therewith. See the previous post on generic variance for an introduction to the topic.The PunchlineThe ECMA 335 Standard, 4th Edition, allows for nondeterministic execution. This means that in certain situations involving generic variance, the specification does not provide sufficient guidance to resolve ambiguities. As you may imagine, nondeterminism is a Very Bad Thing in computing (usually). It means that your program may run one way on .NET 3.5 and another way on .NET 4 and a third way if Richard Stallman saw his shadow in the morning.The SolutionThe ECMA 335 committee is hoping to resolve this problem in the 5th edition. Unfortunately, no clear solutions have revealed themselves. There are a number of possible approaches, all of which have pros and cons. I will be describing the problems and their possible solutions in this post. Feel free to weigh in on the matter. A robust discussion will aid the 335 group in their decision.The Implementation Selection ProblemThere are a number of increasingly pointy corner cases, all variations on the same theme: which of multiple implementation does the runtime select for execution? I will describe these corner cases in order of ascending pointiness. For each case, I will propose a deterministic solution and then demonstrate how that solution fails to address the next corner case. (Note: the deterministic solutions I propose are merely examples. Other solutions could be used.) OverviewBefore getting into the corner cases, I will provide a broad overview of the problem. Ambiguous situations arise when there are multiple implementations of one generic interface (with different type arguments). The generic interface must have some variant generic type parameter.VocabThe implemented types are the closed generic interface types that are actually implemented in the type hierarchy of the object in question.The execution type is the closed generic interface type of the location to which the object is assigned. Calls made to members of this type must be resolved to an implementation among the implemented types.An exact implementation is the implementation of an implemented type whose generic type arguments precisely match those of the execution type. For example, if type A implements the generic interface I, and we assign some A to an I location, then its implementation for that interface is exact.A variant implementation is the implementation of an implemented type whose generic type arguments do not precisely match those of the execution type, but are legal variants thereof. For example, if type A implements the covariant generic interface I, and we assign some A to an I location, then its implementation for that interface is variant.Case 0Nothing to See HereAs a starting point, let us consider the following non-variant scenario which is NOT ambiguous.interface I {    T Next();}class A {}class X : I {    A I.Next() {...}}class Y : X, I {    A I.Next() {...}}// Test codeI i = new Y();A someA = i.Next();ProblemThere are two implementations of I: one in X and one in Y. Which is used for the call to I.Next()?SolutionThe implementation in type Y is used. As I said, this is not actually a problematic situation. I illustrate this case to demonstrate one of the ways the spec currently resolves potential ambiguities. In this case, the implementation in the most derived class is used. Y is more derived than X, therefore its implementation is used.Case 1Easy Pickinsinterface I {    T Next();}class A {}class B : A {}class X : I {    A I.Next() {...}}class Y : X, I&[...]



Exceptional APIs

2009-04-05T02:34:24.182-07:00

Axioms for public API design:Axiom 1NullReferenceExceptions that come out of your code ARE YOUR FAULT!Axiom 2The fewer exceptions your code can possibly throw, the better!Applications of these axioms:Let's say we're writing a public API, you and I. In it, let's say we have the following awesome method:public void Foo(string s) {    Bar(s.Length);}You will notice that we dereference s to get its Length property. If some misguided user of ours were to pass null to Foo, an NRE would pop out of our code like an overweight stripper out of a wedding cake. Awkward! And then the stack trace would get passed all over school and all the kids would laugh at us.Lemma 1From axiom 1 it follows: Null-check EVERYTHING YOU DEREFERENCE unless you know where it came from.We could do a conditional dereference:public void Foo(string s) {    if (s != null) Bar(s.Length);}Or we could verify the argument:public void Foo(string s) {    if (s == null) throw new ArgumentNullException("s");    Bar(s.Length);}If our method absolutely needs to dereference the object in order to do its job, then argument verification is the way to go. This may seem like trading one exception type for another, but it's really not. Argument exception types are perfectly acceptable - they inform our misguided user what went wrong and how to make it right. On the other hand, NREs mean that we didn't verify the argument or null-check before dereferencing. And they mean that all the kids will laugh at us.Let's say that we decide on argument verification. Now let's say that we want to add a convenience overload:public void Foo() {    Foo("");}Looks good, right? WRONG!Lemma 2From axiom 2 it follows: Use 'null' as a sentinel between overloads for the default value when null is not an otherwise permissible value.My favorite non-fiction book of all time, Framework Design Guidelines, specifically says not to do this. It is wrong. Well, sort of. FDG advises against using null as a "magic" sentinel, period. I argue that sentinel null is correct for parameters which are omitted in convenience overloads. Here is why:To recap, our API currently looks like this:public void Foo() {   Foo("");}public void Foo(string s) {    if (s == null) throw new ArgumentNullException("s");    Bar(s.Length);}Let's consider the possible ways our misguided user can use this API. If he or she calls the convenience overload, or passes a string literal, everything's honkey dorey:Foo(); // This is fineFoo("How the hell do I use this API?"); // This too is just fineBut if misguided user passes null to Foo(string), or passes a variable which may be null, things aren't so rosey:Foo(null); // Exception city!Foo(someString); // It depends...How is our misguided user to know what is and is not a safe call? They could look at our documentation. Assuming we wrote any. And assuming we correctly documented all of the parameters which need to be non-null. Or they could test passing null and see if it throws.(As a side note, I wonder all the time about whether I can pass null to an API. Documentation is usually no help and if I see a parameterless overload, I generally assume that I can)More likely, they will do none of the above and just write something resembling the last example call, passing a variable. A variable which is usually not null. A variable which is never null during testing. But a variable which, when released into the wild may, under some unforeseen circumstance, be null. Then all the kids would cry.The solution:public void Foo() {    Foo(null);}public void Foo(string s) {    if (s == null) s = "";    Bar(s.Length);}All possible inputs to this API are valid and there is zero ch[...]



Now Is The Winter of Our Optional and Named Parameters

2009-02-22T04:03:30.421-08:00

Optional and named method parameters are coming to C# 4. This means you can provide default values for method parameters. When you call the method, you can name only the parameters you want to specify - default values will be used for all other parameters.Here's how you use it:public void Foo (    int doodad = 1,    string humdinger = "",    string wuchacallit = "STELLAAAA!"){    // Do stuff here}void Test (){    Foo ();    Foo (humdinger = "Beard Lust");    Foo (doodad = 5,         wuchacallit = "SHAMU!");    Foo (wuchacallit = "Kia",         humdinger = "Ora",         doodad = 42);}Here's how it really works:public void Foo (    [Optional, DefaultParameterValue(1)]    int doodad,    [Optional, DefaultParameterValue("")]    string humdinger,    [Optional, DefaultParameterValue("STELLAAAA!")]    string wuchacallit){    // Do stuff here}void Test (){    Foo (1, "", "STELLAAAA!");    Foo (1, "Beard Lust", "STELLAAAA!");    Foo (5, "", "SHAMU!");    Foo (42, "Ora", "Kia");}The compiler just sprinkles the default values into every callsite. There are a few problems with this approach. Let's suppose I release version 1 of my awesome library with the above Foo method. You compile. All is well. Now let's say I release version 2 of my library, in which the default value "STELLAAAA!" is changed to "KHAAAAN!". But your code still has the old default value baked in. You need to re-compile your code to get the new default value. There is also the problem that injecting the full argument list into every callsite bloats the size of the code. Bigger code means more to JIT and fewer cache hitsHow it should work:struct FooSettings {    int doodad_value = 1;    string humdinger_value = "";    string wuchacallit_value = "STELLAAAA!";    public int doodad {        get { return doodad_value; }        set { doodad_value = value; }    }    public string humdinger {        get { return humdinger_value; }        set { humdinger_value = value; }    }    public string wuchacallit {        get { return wuchacallit_value; }        set { wuchacallit_value = value; }    }}public void Foo (FooSettings settings){    // Do stuff}void Test (){    Foo (new FooSettings ());    Foo (new FooSettings { humdinger = "Beard Lust" });    Foo (new FooSettings {        doodad = 5,        wuchacallit = "SHAMU!" });    Foo (new FooSettings {        wuchacallit = "Kia",        humdinger = "Ora",        doodad = 42 });}Thanks to C# 3's object initialization, you can squint at the call and almost see the named parameter syntax (just ignore "new FooSettings"). This pattern of using a special "settings" type for passing [...]



Generic Type Parameters AS Method Parameters

2009-02-14T01:15:13.332-08:00

I have long had an interest in method contracts (pre- and post-conditions). I followed Spec# and I continue to follow the Pex project. I am also a big fan of doing argument verification at the highest possible level of a public API. I was working on a public API today which takes a Type object. My method looked like this:

public string GetClassName (Type type) {
    if (type == null) {
        throw new ArugmentNullException ("type");
    }

    if (!type.IsSubclassOf (typeof (UpnpObject)) &&
        type != typeof (UpnpObject)) {
        throw new ArgumentException (
            "The type does not derive from UpnpObject.",
            "type");
    }

    // do stuff with 'type'
}


It then occurred to me that I can do the same thing with a generic type parameter, but get all the checks for free!

public string GetClassName () where T : UpnpObject {
    //do stuff with 'typeof (T)'
}


Tada! Using generic type parameters as method parameters is nothing new (Aaron has something like this in the Banshee service stack), but the really neat thing is that you can use the generic constraints as a kind of argument pre-condition. If you have a method which takes a Type, consider using a generic type parameter rather than a method parameter. It guarantees that 'null' cannot be passed and it allows you to specify ancestry, interfaces, ref/value types, and the presence of a default constructor.



C# 4 is NOW!

2009-02-03T21:27:27.529-08:00

WHAT?Generic type variance support just landed in mcs. This is a C# 4 language feature.WHERE?You can give it a go by checking out SVN trunk and compiling your variant code with gmcs -langversion:future.REALLY?Well, this adds compiler support for variance but the Mono VM isn't up to speed on its variance handling. This means that you can compile the code but it won't actually run on Mono (until we fix that, which I am also doing). You can run it on the .NET 2.0 VM.WHAT THE HELL ARE YOU TALKING ABOUT?Generic type variance is like this:Let's say I have some IEnumerable, like so:IEnumerable myStrings = GetSomeStrings ();Now let's say I have some other method which takes an IEnumerable, like so:void DoStuff (IEnumerable someObjects){    foreach (object o in someObjects) {        // do some stuff with each object    }}POP QUIZ: Can I pass myStrings to DoStuff in C# 3? Strings are objects, right? And IEnumerable is just a way of getting Ts. So if strings are objects, and IEnumerable just returns strings, then we can also say that it returns objects. Just like IEnumerable. So it should work, right?ANSWER: Negatorz!This is a problem of generic type variance. There are two kinds of variance: covariance and contravariance. The above example is covarant, meaning that you want to broaden the type of an output. Contravariance is the opposite: narrowing the type of an input. Let's consider a delegate:delegate void Handler (T input);And let's say that we have some Handler:Handler myHandler = delegate (object o) {    // do something with the object}Now let's say that we have a method with takes a Handlervoid HandleStrings (Handler handler, IEnumerable strings){    foreach (string s in strings) {        handler (s);    }}We want to pass myHandler to HandleStrings. A Handler takes objects, and strings are objects, so anything which is a Handler should also be a legal Handler. This is an example of contravariance.It may surprise you to know, but the CLI has supported generic type variance since version 2. The rules are:Variant type parameters are only allowed in interfaces and delegate types.Contravariant type parameters can only be used as by-value method parameter types.Covariant type parameters can only be used as method return types and generic arguments to inherited interfaces.Only reference types are variant (this isn't explicitly stated in the spec, but it is the case).Languages may choose to ignore variance and treat all generic parameters as invariant.For whatever reason, the C# language team has so far chosen not to support generic type variance. Well, that will be changing in 2010. The preview given by Anders Hejlsberg at PDC '08 revealed that C# 4 will finally support variance. But who wants to wait? Especially considering that this has been a .NET VM feature since 2006. So you can now use this in gmcs if you pass -langversion:future.Covariance (which, as you will remember, can only be used as a method return type or as a generic argument to an inherited interface) is denoted with the "out" keyword before the type parameter identifier:interface IFoo : IBar{    T Bat { get; }}Contravariance (which is legal only as the type of a by-value method parameter) is denoted with the "in" keyword:interface IFoo{    void Bar (T bat);}So there you go! Now we just need to get Mono's VM va[...]



Equality Now!

2008-11-29T21:07:51.967-08:00

There are three primary ways to handle equality in .NET: overriding Object.Equals, overloading the == and != operators, and implementing IEquatable. Framework Design Guidelines offers pretty good advice on when to use what. A quick summary:If you want custom equality logic, whatever else you might do, override Object.Equals. This method is used by the various data structures in System.Collections (and elsewhere in the BCL) to determine equality. It's the first best way to do equality.IEquatable should be implemented by structs with custom equality. Because calling Object.Equals on a struct involves boxing, and the implementation for value types uses reflection (!!!!!), IEquatable gets around both of those problems. When implementing IEquatable, always override Object.Equals as well.Operator overloading is a little bit tricky because it's really just a compiler feature. The compiler has a lookup rule for the operator implementation which takes the most derived types along the operands' type ancestry. Whereas Object.Equals is a virtual method whose overridden implementation will always be used, overloaded operators will only be used if both operands are of static (compile-time) types that are or derive from the types specified in the overload. Overloading operators is a matter of discretion. It's more commonly done with value than reference types. If you overload the equality operators, also override Equals (an implement IEquatable if the type is a struct).When you are just overriding Equals, here is the pattern I find works the best:public override bool Equals (object obj){  MyRefType mine = obj as MyRefType;  return mine != null && /* custom equality logic here */;}If you want to overload operators and it's a reference type, here's the thing to do:public override bool Equals (object obj){  MyRefType mine = obj as MyRefType;  return mine == this;}public static bool operator == (MyRefType mine1, MyRefType mine2){  if (Object.ReferenceEquals (mine1, null)) {    return Object.ReferenceEquals (mine2, null);  }  return !Object.ReferenceEquals (mine2, null) &&  /* custom equality logic here /*;}public static bool operator != (MyRefType  mine1, MyRefType  mine2){  return !(mine1 == mine2);}If you have a value type, here's the scenario without overriding the operators.public override bool Equals (object obj){  return obj is MyValueType && Equals ((MyValueType)obj);}public bool Equals (MyValueType mine){  return /* custom equality logic here */}And here's the value type with operator overloadspublic override bool Equals (object obj){  return obj is MyValueType && Equals ((MyValueType)obj);}public bool Equals (MyValueType mine){  return mine == this;}public static bool operator == (MyType mine1, MyType mine2){  return /* custom equality logic here */}public static bool operator != (MyType  mine1, MyType  mine2){  return !(mine1 == mine2);}The purpose of the above patterns is to centralize the equality logic in one place. You'll notice in the example which uses all three approaches, the == operator is the only place with actual equality logic. I find this just makes thing easier. If you want, you can have custom logic in the != overload (the logical inverse of ==), but that means you have to make changes in two places if you alter the equality logic, and it's really easy to make a mistake with logic operators.Want to share your tips for equality? Have a better pattern? Leave a comment![...]



Advanced Topics in Inefficiency: Anonymous Methods

2008-11-05T19:36:53.629-08:00

This is the first in what may be a series of posts on various theoretical (and not so theoretical) corner cases in common code. Despite being obtuse, these issues are useful to explore both to avoid inefficiencies and to better understand what's happening behind the code. Today's topic: anonymous methods.class Foo(){    void Bar()    {        var thing1 = new Thing();        var thing2 = new Thing();        DoSomeStuff (() => thing1.Shimmy());        DoOtherStuff(() => thing2.Shake());    }}There is a potential memory problem with this method. It's not obvious from looking at the code, but both things must be garbage collected together. As long as there is an active reference to one, the other will live on as well. If 'Thing' is a heavy type, this could keep significant memory from being reclaimed on the heap. To better understand, let us look at how the C# compiler handles anonymous methods.The above example demonstrates "local variable capture." This means local variables from the enclosing method body can be used inside closures (such as the two lambdas above). To accomplish this, the C# compiler shunts the values of the local variables to an object. The type of the object is generated by the compiler. In essence, the compiler turns the above code into this:class Foo(){    class GeneratedTypeForMethodBar    {        public Thing thing1;        public Thing thing2;        public void AnonymousMethod1()        {            thing1.Shimmy();        }        public void AnonymousMethod2()        {            thing2.Shake();        }    }    void Bar()    {        var closure_object =            new GeneratedTypeForMethodBar();        closure_object.thing1 = new Thing();        closure_object.thing2 = new Thing();        DoSomeStuff(closure_object.AnonymousMethod1);        DoOtherStuff(closure_object.AnonymousMethod2);    }}This is actually a very clever way of achieving local variable capture since it makes use of the CLI's pre-existing garbage collector to clean up the captured variables. The problem is, the compiler shunts all local variables to a single object. In our above example, the two anonymous methods do not reference any of the same local variables, but both local variables are stored in the same object. This can lead some captured variables to become prisoner variables: they are no longer needed, but they cannot be garbage collected. Suppose that our 'DoSomeStuff' method just invokes the delegate and returns. No problem. But now suppose that our 'DoOtherStuff' method holds on to the delegate, perhaps planing to invoke it later. Or suppose we were to return the second lambda, allowing the caller to hold the delegate as long as they please. That[...]



Mono.Upnp: A Bun In The Oven

2008-10-10T03:13:06.218-07:00

Aaron's post has piqued some interest, so I thought I'd give up the goods.

WTF
Mono.Upnp is a fully managed UPnP implementation. The client and server stacks are in separate libraries to give embedded devices a compact solution for either. The client library is a solid implementation of the UPnP standard designed to robustly cope with other, less compliant UPnP devices (seriously, no one actually implements the UPnP standard correctly. Especially not router manufacturers, may they die a thousand deaths). The client API is also highly extensible, allowing easy consumption of services which offer functionality not established in the spec. The server library offers developers an easy way to expose their services over UPnP: attributes indicate UPnP-visible members and the library handles all of the network plumbing. In addition, all of the official UPnP device and service APIs (the specs which sit on top of the UPnP architecture - for example, the MediaServer API) are wrapped both for client and server use.

Holy Shit!
Indeed. Well, almost. All of the above sounds great, but it's not done yet. In fact, it's still quite experimental. While I've made great progress in impressive screenshots, actually listening to your Banshee collection on a PS3 is still a few hack-o-thons off. But things are moving along nicely and I will certainly keep you up to date.

OK
In the mean time, curious monkeys can find the source in the mono-upnp module of the Mono SVN. Like I said, you shouldn't be using this code, but you're welcome to check it out.



MemberExpression Question

2007-11-01T13:23:12.682-07:00

Maybe someone can answer this for me. When C# is compiled into an Expression tree, the MemberInfo that is tied to a MemberExpression points to the most virtual/abstract definition of that member. For an example, take a look at this code. The Visitor class will print the declaring type of a member encountered in a MemberAccess Expression (ln 36). When ran in Orcas B2, it prints "BaseClass" rather than "ConcreteClass". Is this how it's supposed to behave? Does Mono behave this way? Is there a better way to get the MethodInfo of the concrete class than this:

// This goes in the Visitor.VisitMemberAccess method
MemberInfo mi = m.Expression.Type.GetMemeber(m.Member.Name)[0];

I ask because I'm looking for custom attributes which may only exist on the overridden members of the concrete classes.



Linq Me This Nut

2007-11-01T11:48:19.661-07:00

The Banshee-to-Windows porting has been more or less done for a while and the code is about to be integrated into trunk. Since the end of the SoC, I've been occupying myself with a tangentially related project. Banshee talks to the MusicBrainz database to get metadata on CDs. Currently it calls into the unmanaged libmusicbrainz library which is both old and no fun. Enter musicbrainz-sharp, my new project to implement a fully managed API for MusicBrainz. It's a very nice OO encapsulation of MusicBrainz's XMLWebService and it's really easy to use:

Artist a = Artist.QuerySingle("The Magnetic Fields");
foreach(Release r in a.Releases)
    Console.WriteLine(r.Title);

Right now it lives in banshee's svn (thanks to Aaron for setting me up with autotools et al). The API is 90% done, the documentation is 90% written, and the unit tests are at about 50% coverage. It's been my intension to create a Linq provider when 3.5 comes out, but for whatever reason the urge overcame me today. I did a quick job which only supports very specific cases, but the following code now works like a charm in Orcas:

var query = from a in MB.Artists
            where a.Name == "Goodshirt"
            select a;

foreach(var artist in query) {
    Console.WriteLine(
artist);
    foreach(var release in artist.Releases) {
        Console.WriteLine("\t{0}", release);
        foreach(var track in release.Tracks)
            Console.WriteLine("\t\t{0}", track);
    }
}


I was muy excited. There's some boilerplate code involved with writing a Linq provider. I hope Microsoft adds some base classes to the API. Linq is balls awesome!



Status Report Aug 5

2007-08-05T23:11:02.766-07:00

This week:
  • CD Burning is done
  • CD Playback is done
  • NotifyAreaPlugin works with the Windows system tray
Things are really coming together. I'll have new screenshots soon but I've got to go to bed now. We're out of the native code woods... for now.



End of July Status

2007-07-31T20:44:08.885-07:00

Here's the skinny on the Banshee port to Windows:Major re-factoring of the audio CD code. I abstracted a bunch of Linux-specific code and implemented classes for Windows. Made some interfaces into abstract classes where helpful and re-jiggered some of the architecture.The Cool Thing: It's all really pretty and audio CD detection works.The Not Cool Thing: CD playback does not work. This is because Gstreamer on Windows doesn't handle cdda:/ URIs. This is because libcdio doesn't build on Windows. This is because, while it used to build on Windows, the Visual Studio solution has terrible bitrot. Solutions:Build with Cygwin and...Live with a dependency on cygwin0.dll, orFind some way of circumventing cygwin dependencies (ideal).Fix the Visual Studio solution. This consumed much of my time recently. I emailed the guy who previously maintained the VS solution, but he hasn't gotten back to me.Write a new cdda handler for Gstreamer using the Win32 API. Ug.Implementation of CD burning for Windows.The Cool Thing: It's partially done (and was loads of fun), but I need to be able to test it to continue with the work.The Not Cool Thing: I can't test it. This is because Banshee's Gstreamer transcoding code doesn't work. This is because it references libgnomevfs-2-0.dll and there is no libgnomevfs-2-0.lib against which to link and when I link against libgnomevfs-2-0.a, Visual Studio produces a malformed DLL which crashes upon loading. Solutions:Build gnome-vfs with MSBuild. I gave that a try and it looks like a lot of work before it will work.Contact whoever maintains Mono's Windows binaries and ask for their advice (ideal).Remove the gnome-vfs code from libbanshee.Improvements to importing from iTunes.The Cool Thing: Following Jonathan Pryor's post on monodocer performance, I switched from XmlDocument to XmlTextReader. Much memory savings. Not a lot of speed savings (XML handling isn't a bottleneck).The Not Cool Thing: Nothing. The code is faster and prettier.Misc. Other Things:I'm hoping the Gstreamer people will add a function export that I need: _gst_plugin_register_static. It's in the code but it just isn't exported for Windows. Waiting to hear back.The CD reading and burning code are from code example sites. Both are just encapsulation of COM interfaces. I'm 99% sure the CD reading code is license compatible (I'm still looking into it), but the CD burning stuff defiantly isn't. I've contacted both authors to see if they will release the code under MIT/X11. Waiting to hear back. If I can't get clearance, I'll have to do the COM wrappings myself. Ug.Gtk is slow on Windows. Even when not debugging. Aaron's new view model should make things much better.Gstreamer is slow on Windows. It's fine most of the time, but when the CPU gets hammered, the audio will become choppy. This doesn't happen when using DirectSound in similar situations. I don't know yet if it's a significant problem.I find I'm spending most of my time struggling with unmanaged code. When I tackle a new problem, like audio CDs, I hammer out the C# lickety split and have a great time. But then I hit a snag in native land (like the cdda/libcdio problem) and spend days trying to sort out the C libraries which is no fun. After a few days of wrestling with unmanaged code, I'll put it on the back burner and start on something else (CD burning or iTunes importing, for instance) but I really need to address these native issues. Tomorrow I'll start emailing around and see where I can get with cdda support in Gstreamer or gnomevfs linking on Windows. If you have info on this stuff, especially usin[...]



Using Glib Callbacks with Managed Delegates on Windows

2007-07-14T16:09:43.127-07:00

After wrestling with GStreamer for a week on Windows, I was delighted and disgusted to learn that the solution to my problem involved a simple string manipulation. My grin was mighty toothy. Sharp teeth.I then had a new problem: Native Banshee code needs to call managed Banshee code every now and again (every 200 milliseconds) while Gstreamer is GStreaming. These callbacks are handled on the unmanaged side with glib mechanisms such as g_timeout_add. The problem is, glib uses the cdecl calling convention. If you try to set up a callback to managed delegates, which do not use the cdecl convention on Windows, you'll hit a nasty error when you call a delegate. Specifically, you'll encounter my good friend, the every-cryptic, "An unhandled exception of type 'System.AccessViolationException' occurred in gtk-sharp.dll".The solution (thanks Miguel) is round-about, but with some jiggering in Visual Studio 2005 you can Set it and Forget it©. Here's the step-by-step:Download and install ActivePerl for Windows.Grab gtk-sharp/gapi-cdecl-insert. I just put it in C:\You may need to edit gapi-cdecl-insert depending on whether or not I've committed these changes to SVN by the time you read this. Look at line 36. If it looks like this:`ildasm $assembly /out:$basename.raw`;Then you need to change it to this:`ildasm "$assembly" /out:"$basename.raw"`;(Add quotes to $assembly and $basename.raw). Do the same for line 49 by putting quotes around $basename.il, if they aren't already there.Specify the Glib.CDeclCallback attribute for each delegate definition you will be calling with glib. For example:[GLib.CDeclCallback]internal delegate void GstPlaybackEosCallback(IntPtr engine); Open the Properties for the C# library project with the delegates of interest.Open the Build Events tab.Click the Edit Post-build button.First add the following:Call "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sdkvars.bat"Obviously, adjust the install path for Visual Studio as necessary (there is no sufficient macro; grrr).On the next line, add this:Call C:\Perl\bin\perl.exe C:\gapi-cdecl-insert "$(TargetPath)"Again, adjust your Perl and gapi-cdecl-insert paths as appropriate.For whatever reason, VS fucks up the Perl script at the end, so you need to add one final line to the post-build events:Call ilasm /DLL /QUIET /DEBUG "$(TargetDir)\$(TargetName).il"Remove the /DEBUG flag when you build for release.Now try not to have too much fun fixing your glib-facilitated unmanaged-to-managed callback functions on Windows!Update:Great and terrible news! None of the above craziness is necessary. Thanks to Jonathan Pryor who points out in the comments that all you need to do is specify the [UnmanagedFunctionPointer(CallingConvention.Cdecl)] attribute for the delegate definitions. No Perl necessary! This only works for the 2.0 framework.[...]



More News from the Front!

2007-06-25T10:53:56.629-07:00

A quick update on two exciting developments:
  • Banshee now works on the .NET VM. Thanks to a tip from Javier of the Bibli@teca project who directed me toward a different set of GTK libraries.
  • Banshee now plays music. I've written a little DirectShow backend which provides all the niceties of playback: play/pause, seeking, volume control, &c. This is a temporary solution until I get GStreamer working, but it's nice to see this sucker actually do what it does.
That's all for now.



Eets Alive!

2007-06-20T20:58:15.105-07:00

After weeks of fiddling and false starts, this was the scene on my screen some 120 seconds ago:

(image)
Banshee on Windows, baby!



Status Report 1

2007-06-02T14:54:00.179-07:00

Well, not much to report unfortunately. I've been desperately trying to get all of the build dependencies up and running on Cygwin. No easy task. For a detailed account of everything involved, and for a continued report of progress, see my project scratch pad. Aaron is moving right now so I'm one my own for the next week or so. I'm going to concurrently start work on the port while I try to get my Windows development environment up and running.

As a post-script to my last post, I also added C# 3.0 Automatic Properties to gmcs. Look for that in SVN!



3rd is the one with the treasure chest

2007-05-07T23:43:53.427-07:00

I seem to be on a compiler bent. I just committed the following C# 3.0 features to gmcs:
  • Variable type inference (the "var" keyword)
  • Anonymous types.
  • Implicitly typed arrays.
  • Object initialization.
  • Collection initialization.
They're in SVN right now, so go check 'em out! A word of warning: the new compiler errors associated with these features are not in place yet, so only write perfect code.

This is my first time under the hood of a compiler (other than my brainfuck compiler). It took me a while to get my bearings but once I was acclimated, everything went smooth like bunnies. mcs is great to work on: it is very well designed. The foundation for all of these new features (particularly anonymous types) was already in place, I essentially just handled the new syntax. Thanks goes to Marek Safar for his help.

Of course, all of these features are so much pretext for LINQ. Atsushi Eno is working on LINQ for XML and Antonello Provenzano has begun LINQ for SQL. Most of my hacking time this summer will go toward my Summer of Code project but if I have extra time I will defiantly look to the Olive project's LINQ implementation.



It Begins

2007-04-11T21:46:11.223-07:00

First posts are hard to write so I'll do what I do best: talk about myself. I'm Scott Peterson. I attend New York University and my birthday is coming up soon (April 23rd). I enjoy whole milk and correcting people's grammar (but not their spelling).

Here is a picture of me eating a taco:

(image)
Now that we're acquainted, let's to 't. This blog chronicles my Google Summer of Code project to port Banshee to Windows. I may also occasionally post about my other OSS/Mono exploits. For example, I just finished a brainfuck compiler for the CLI (.NET & Mono). It is called brainfucker. It is written in C# and uses the fantastic Mono.Cecil library (cred to JB Evain). It also has a Gtk interface, if that's your thing.

Well, that's all for now. This is surely the beginning of something magnificent. I feel it in my bones!