Posts tagged with c - page 14

Substitutability of generic types in .NET

The “is” operator

Anyone using object orientated programming soon finds themselves wanting to perform some action only if an object is of some type or implements some interface.

The easiest way is to do this is to use the “is” operator. Typically it will appear something like;

object objA = FunctionToGetAnObject();
if (obj is SomeClassOrInterface)
    ((SomeClassOrInterface) obj).SomeMethod();

Here if obj_A is of a type that implements SomeClassOrInterface anywhere in its inheritence tree then SomeMethod of SomeClassOrInterface will be called.

Test substitution with generic types

Now lets say we have our own generic type – here’s one to illustrate a point;

public class DamoClass<T> {
    public T GetProperty { get { ... } }
    public T SetProperty { set { ... } }
    public bool IsValid { return true; }
}

If we want to check obj_A supports DamoClass<T> but we don’t care what type T is you might expect to be able to perform;

if (objA is DamoClass)

But that results in a compilation error – you can’t reference a generic class without specifying the type parameters regardless of whether you care about them or not. You might then try;

if (objA is DamoClass<object>)

After all every class inherits from object. This compiles fine but at runtime if objA is of any type other than object, e.g. DamoClass<string> it will return false.

Why?

The following might be what you had in mind;

if (objA is DamoClass<object>) {
    ((DamoClass<object>) objA).IsValid();
    object test = ((DamoClass<object>) objA).GetProperty;
}

Which looks fine but if .NET allowed that then how would it prevent;

if (objA is DamoClass<object>)
    ((DamoClass<object>) objA).SetProperty = 11;

When objA.AssociatedObject might well be something other than an integer? It can’t – so it doesn’t.

Solution

The solution is to split your generic class into two classes.

The first contains your non-generic methods and properties and the second inherits from the first adding all the generic specialisation. The good news is that they can even have the same name.

public class DamoClass {
    public object GetProperty { get { ... } }
    public bool IsValid { return true; }
}

public class DamoClass<T> : DamoClass {
    public T SetProperty { set { ... } }
}

Then you are free to do;

if (objA is DamoClass) {
    ((DamoClass) objA).IsValid();
    object test = ((DamoClass) objA).GetProperty;
}

Indeed .NET itself uses this technique for IEnumerable and IEnumerable

One drawback with this technique is that you can’t redefine the type of a member in the subclass – maybe that’ll make C# 3.0.

[)amien

Handling nullable value types in .NET 1.x

One of the great new features in .NET 2.0 is support for nullable types – especially important when dealing with value types such as Int or DateTime values coming from a database. Previously you were forced to either set and track another binary flag or to use a “special” value to represent null that sooner or later would turn up in real data.

In C# 2.0 thanks to a bit of syntactic sugar we can do this;

int? nullable1 = 1;
if (nullable1 == null) nullable1 = 2;

Which the C# compiler actually turns into the following:

Nullable<int> nullable1 = new Nullable<int>(1);
if (!nullable1.HasValue) nullable1 = new Nullable<int>(2);

This makes use of the new Nullable generic structure to wrap the value with an additional boolean HasValue property.

That looks surprisingly similar to the syntax of the open-source NullableTypes project you can use with .NET 1.1 (or 2.0):

NullableInt32 nullable1 = new NullableInt32(1);
if (nullable1.IsNull) nullable1 = new NullableInt(2);

Disclaimer: I’ve worked on the NullableTypes project specifically implementing the IXmlSerializable, NullableGuid & NullableTimeSpan.

[)amien

Do not expose the implementation

One of the things we are taught in object oriented design is that the outside world should not be exposed to the complexities of how our object achieves their goals. Other developers are busy, don’t care and really don’t need to know. It is a sound idea and goes hand-in-hand with ease of use.

Televisions used to expose the implementation with a single tuning knob that had to be adjusted every time you wanted to watch another broadcast. With time engineers replaced this with an interface that hid the implementation, specifically the concept of channels where each one could be individually tuned and switched between on a whim. Implementation no longer exposed.

Technology brings complexity but only good technology makes it look simple.

One thing that has always annoyed me here in the UK is an every day object that doesn’t hide the implementation.

Taps.

That’s right taps. I don’t care that water is delivered to my sink through two pipes, hot and cold. I don’t ever want scolding hot water and just as rarely require it uncomfortably cold. Most of the time I want the same warm temperature as last time.

Sure, there are taps that do this and indeed in many other countries it seems to be the norm but here in the UK builders keep putting in separate hot and cold taps in. Until either the public wise up or I actually buy my own house and can replace this sort of annoyance I’m stuck with it.

While taps have annoyed me for a while it was .NET 2.0 that reminded me of the whole issue again and a brief discussion with GrinGod that caused a similarly titled post of his own. Specifically the Hashtable class is now called Dictionary when used with generics which once again prevents the implementation details leaking out into your code. Important in this case because most people wanted a fast dictionary and didn’t care too much how it was achieved and also because that algorithm changed in .NET 2.0 and they realized they shouldn’t have specified the implementation in the class name…

If you previously generated strongly-typed collections in .NET 1.1 using the many tools around such as CodeSmith then you might be interested in this little tip. If you have a strongly typed class such as:

public class MyObjectCollection : Hashtable {
  public MyObject this[object key] {
    get { return (MyObject) pHashtable[key]; }
    set { pHashtable[key] = value; }
  }
}

Then instead of replacing every single instance of

var theseObjects = new MyObjectCollection();

with

var theseObjects = new Dictionary<object, MyObject>;

you can in fact simple change MyObjectCollection and leave the rest of your code alone:

public class MyObjectCollection : Dictionary<object, MyObject> { }

Which will also mean that you can still have the additional properties and functions on MyObjectCollection if you had them previously. It’s rather obvious you can do this but many samples I’ve seen just create raw generic collections everywhere rather than inheriting from them.

[)amien

NullableTypes 1.3.1 beta

In my early .NET days I ran into a problem many developers integrating with other systems do. Unlike XML with it’s xsl:nil or database fields with <null> the standard .NET value-types don’t support the concept of null for missing values. It’s such an important omission that Microsoft implemented it in .NET 2.0 (now gone RTM and up on MSDN) with a generics class named [Nullable](https://msdn2.microsoft.com/en-us/library/1t3y8s4s%28en-us,vs.80%29.aspx) and a little syntactic sugar to help it go down smoothly.

For those of us still working with .NET 1.1 the NullableTypes project provides null-capable versions of all your favorite .NET types and unlike the SqlTypes included in .NET these match the System types for precision and provide support for .NET remoting and web services.

Yesterday NullableTypes 1.3.1 beta was release which adds (since the last 1.2 stable release):

  • New types (NullableGuid and NullableTimeSpan)
  • DateTime.Add method returns new instance in keeping with the the other immutable classes
  • Security enhancement (reduced needed permissions/attack surface)
  • NullableInt16.GetHashCode now returns hash codes identical to Int16
  • Improvements and additions to the unit tests

With my contributions now including NullableGuid, NullableTimeSpan and implementing IXmlSerializable I am finally feeling like an open source/free software contributor.

I’ve got a few more ideas for NullableTypes that I’ll be working through with LuKa around unit testing and .NET 2.0 source compatibility.

[)amien