deft flux

A portal into the creative workings of David Meyer

Home

Welcome to my site.  Below are some highlights of the site followed by recent blog posts:

  • Duck Typing Project - A .NET class library written in C# that enables duck typing for any .NET language. The library has come to support many advanced features such as covariance and contravariance in class members.

Comments are working now

Comments mysteriously started working now.  Huh.  Please e-mail me if you have any trouble leaving a comment now.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General
Posted by deftflux on Friday, October 19, 2007 10:37 AM
Permalink | Comments (3) | Post RSSRSS comment feed

New band page up on MySpace

I just put up a band page on MySpace to host my music.  There is currently one track up.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General | Music
Posted by deftflux on Friday, October 19, 2007 8:30 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Trick to refer to objects of generic types

I realized something while I was working on a project.  I thought it might be a useful idea, so I thought I'd write a post.

To help clarify the following, I will be using the terminology for generics as it appears in System.Reflection.  List<T> is an example of a "generic type definition", because its type arguments have not been specified.  Whereas List<string> is a "generic type".  T is a "type parameter" and string is a "type argument".

In .NET (C#), while a generic type definition can be referenced using typeof (e.g. typeof(List<>)) in order to get a Type object, you cannot declare a variable with a generic type definition type.  This is because the generic type definition isn't really a type in .NET, it's more of a template for a type.  Furthermore, generic types from the same definition do not automatically inherit from a common base class.  This presents a problem when you want to be able to reference an object of a generic type without knowing its type arguments.

I ran into this problem yesterday.  I realized, however, that since types can be distinguished by how many type parameters they have, a type that is not generic and a generic type definition with one or more type arguments can both be defined without causing a naming conflict.  This can commonly be seen with the old System.Collections classes and interfaces and the new generic System.Collection.Generic types (e.g. Stack vs. Stack<T>).

So I performed a little trick taking advantage of this in order to solve the above problem.  Here's some example code:

public abstract class TransactionField
{
    
}

public class TransactionField<T> : TransactionField
{
    private T m_Value;
    
    public T Value { get { return m_Value; } set { m_Value = value; } }
}
 

Now an object of any TransactionField<T> type can be referenced as simply TransactionField.  This is great for referencing, but what about that Value property?  What if you need to be able to access that property for any TransactionField<T> object?  Check this out:

public abstract class TransactionField
{
    public object Value { get { return _Value; } set { _Value = value; } }
    
    protected abstract object _Value { getset; }
}

public class TransactionField<T> : TransactionField
{
    private T m_Value;
    
    public new T Value { get { return m_Value; } set { m_Value = value; } }
    
    protected override object _Value { get { return Value; } set { Value = (T)value; } }
}
 

It gets a little confusing with the naming.  But basically, TransactionField defines an protected abstract property _Value so that it can access the value stored in types derived from it.  It also defines a public property Value which provides public access to the value stored in the derived type via _Value.  Finally, TransactionField<T> defines a new property with the same name Value except this one uses the type argument instead of object.  

Now at this point, you might be wondering what the point of using generics at all in this scenario is.  Well, TransactionField<T> replaces the Value property with a typesafe one.  When you deal with the generic type, you won't need to cast any values.  This approach is the best of both worlds.  The object can be dealt with as an object of a generic type or a non-generic type, depending on what is needed for the code that is using the object.

Currently rated 3.8 by 5 people

  • Currently 3.8/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Development
Posted by deftflux on Thursday, October 11, 2007 10:45 AM
Permalink | Comments (1) | Post RSSRSS comment feed

Some descriptive exception messages, please?

Today I encountered an exception thrown from a class library I was using that had an interesting exception message.  Actually, the only thing interesting about it was how completely useless it was.  Without revealing the identity of the class library, I will paraphrase.  I was calling a method called "Initialize" on an object of a class, which I will call MyClass for ambiguity.  The exception message was...

"Failed to initialize MyClass"

Ok, let's examine this for a moment.  "Initialize" is the name of the method and, thus, what the method is supposed to do, which is what this is saying it failed to do.  Let me illustrate how meaningless this is by saying it with a slightly different wording:

"The method you just called failed to do what it is supposed to do to the object it was called on because of an error that we are going to tell you nothing about.  In fact, the original exception would have given you some useful information to go off of, but we decided to catch this exception and throw you this useless one instead, without even referencing the original as the inner exception we might add, because we enjoy frustrating our customers.  It's all part of our elaborate plan to make you contact us to help you solve the issue.  This way we appear needed to our employer even though we are lazy and continue to write crappy code.  We don't care that this wastes your time and contributes towards delaying the very time-critical project you are trying to finish while your boss rides you every day about where you are on it.  All we care about is keeping our jobs since we haven't the slightest clue what we're doing here."

The person I talked to today was lucky that I'm generally a nice guy, otherwise her day might have turned real ugly.  But, fortunately, it didn't waste too much time--if half the day doesn't count as too much time, that is.  It turns out the problem was quite simple.  The error could have easily been summarized in an exception message like "The given system name was not found on the given server."  Now would that have been so hard for the programmer who wrote that method to type that instead of "Failed for some reason"?

So next time you find yourself starting a line of code with "throw new", please, for the sake of programmers everywhere, at least say something about what the problem is, and include the original exception, if any, as the inner exception.

P.S. Comments are still not working...  Sorry.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Development
Posted by deftflux on Tuesday, October 09, 2007 2:27 PM
Permalink | Comments (0) | Post RSSRSS comment feed