Archive for the ‘C#’ Category

On duck typing and interfaces

Wednesday, January 2nd, 2008

I was looking at different type systems (apparently there are 4 dimensions) in different languages and ran across this use of duck typing in C# :

For example, the C#’s foreach operator already uses duck typing. This might be surprising to some, but to support foreach in C# you don’t need to implement IEnumerable! All you have to do is:



Provide a public method GetEnumerator that takes no parameters and returns a type that has two members: a) a method MoveMext that takes no parameters and return a Boolean, and b) a property Current with a getter that returns an Object.

Do you have multiple fine-grained interfaces (like IEnumerable and IEnumerator and ISupportsAdd) or a single interface with all the methods and maybe they throw UnsupportedOperationExceptions if they don’t actually support a particular call (like in a mutable versus immutable collection)?

The closer you get to more fine grained interfaces like ISupportsAdd<T> or Closeable, defining a contract for a single method Add(T obj) or Close is that you might as well just ask the class if it has that method (if it “quacks”) instead of whether it implemented a single method interface. Better yet, just assume it and let it throw an error at runtime. Whatever the compiler doesn’t give you, some decent test coverage will.

But what strikes me as particularly great is that foreach is obviously such a powerful thing to restrict to a single interface, and so they chose “Duck Notation”, because in this case it is worth it.

This reminded me of why I like ecma 4 (and its derivatives like actionscript). You have freedom to use static and dynamic typing at will.

If you check out my take on an AS3 HTTP client library, HttpRequest class and allowing the request body to be of any type:

public class HttpRequest {
 
  // Request method. For example, "GET"
  protected var _method:String;
 
  // Request header
  protected var _header:HttpHeader;
 
  // Request body
  protected var _body:*;
 
  /**
   * Create request.
   *  
   * The request body can be anything but should respond to:
   *  - readBytes(bytes:ByteArray, offset:uint, length:uint)
   *  - length
   *  - bytesAvailable
   *  - close
   *  
   * @param method HTTP Method, for example 'GET'
   * @param header HTTP request header (or null)
   * @param body HTTP request body (or null)
   *  
   */
  public function HttpRequest(method:String, header:HttpHeader = null, body:* = null) {
    _method = method;
    _header = header;      
    _body = body;
 
 ...

I think this is a good choice because:

  1. The IDataInput interface (that ByteArray already implements) doesn’t have a length property and we need to know the request body size (Content-Length) before we send.
  2. The IDataInput interface wants you to implement a ton of read methods, which would make it annoying to force people to implement.
  3. ByteArray has these methods and also implements the length property already. It quacks.
  4. If we created our own interface with these methods, we can’t add this interface retroactively to ByteArray.
  5. I wrote it. Heh.

The other option is to subclass ByteArray and have that implement the new interface, but it just seems awkward (in this case) having any empty subclass solely for the point of enforcing an interface.

Another place where this principle applied for me is in HttpSocket. We need to support both Socket (for http) and TLSSocket (for https). TLSSocket has all the same (mostly) methods as Socket (but does not extend Socket; yay for composition over inheritance). Creating a proxy to delegate to different socket implementations based on the http scheme is an option but to me wasn’t worth it. And using a design pattern to overcome the lack of an appropriate and existing interface just seems to make things worse.

Open sourced (Flickr OpenGL C# Library)

Tuesday, March 20th, 2007

Crossposted from cellardoorsw.com:

I GPL licensed all the source to Slickr (that I wrote), and released it into the wild. You can view the trac page, or go straight to the source. Its all C# and OpenGL goodness with some gnarly calls to some windows api’s (for extra’s nothing critical). There are a couple NAnt build scripts for when I was trying to get it working under linux, but you’ll want Visual Studio (2003) to get started quick (and look at the README).
Who knew it would be such a pain to draw text and did I really need to query the monitor power state?

I’ll try to write an overall design doc soon, but until then start at any of the Entrypoint’s. And in the end all that is really going on is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private void DrawGLTexture(SlickrImage image)
{
  PointFloat p = image.GetMovement(window.Width, window.Height, true);
  float scale = image.GetScale(window.Width, window.Height);
  float fade = image.GetPercentageFade();
  int texWidth = image.TextureWidth;
  int texHeight = image.TextureHeight;

  Gl.glMatrixMode(Gl.GL_PROJECTION);                                  // Select The Projection Matrix
  Gl.glLoadIdentity();                                                // Reset The Projection Matrix
  float r = (window.Width/scale);
  float b = (window.Height/scale);

  Gl.glOrtho(0, r, b, 0, -1.0f, 1.0f);
  Gl.glMatrixMode(Gl.GL_MODELVIEW);                                   // Select The Modelview Matrix
  Gl.glLoadIdentity();

  Gl.glEnable (Gl.GL_BLEND); // for text fading
  Gl.glBlendFunc (Gl.GL_ONE, Gl.GL_ONE_MINUS_SRC_ALPHA);
  Gl.glColor4f (fade, fade, fade, fade);

  float posX = p.x; //stepX +
  float posY = p.y; //stepY +

  image.DrawAtPoint(posX, posY);

  Gl.glDisable(Gl.GL_BLEND);
}

If you are interesting in working on bug fixes, enhacements, or whatever give me a shout.