Mr. Boy
Mr. Boy

Reputation: 63728

How to write an extension method that can return different types for the same input?

I want to write something like this:

    public static Int16 Parse(this byte[] buffer, int index)
    {
        var v = buffer[index++] << 8;
        v += buffer[index++];
        return (Int16)v;
    }

    public static Int32 Parse(this byte[] buffer, int index)
    {
        var v = buffer[index++] << 24;
        v += buffer[index++] << 16;
        v += buffer[index++] << 8;
        v += buffer[index++];
        return (Int16)v;
    }

But this isn't valid. I thought I could use generics:

    public static Int16 <Int16>Parse(this byte[] buffer, int index)
    {
        var v = buffer[index++] << 8;
        v += buffer[index++];
        return (Int16)v;
    }

But this does weird things:

Is there a way to do what I want with explicit generic parameters?

In a perfect world I would add extensions to Int16 and Int32 but extension methods have to be called on object instances, not called like Int32.Parse()

Upvotes: 2

Views: 401

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1062780

The usual solution here is simply to use different names - usually a suffix based on the type.

In this specific case, your methods are redundant - there are framework methods for this, at least in some frameworks; you're essentially re-implementing:

  • BinaryPrimitives.ReadInt16BigEndian(...)
  • BinaryPrimitives.ReadInt32BigEndian(...)

(there is a slight difference re how the offset is specified; in the BinaryPrimitives version using spans, the offset is achieved via Slice)

Upvotes: 1

Peter Duniho
Peter Duniho

Reputation: 70671

Is there a way to do what I want with explicit generic parameters?

No.

I mean, you could declare the method as T Parse<T>(this byte[] buffer, int index), which would solve the return value issue. But, in the method you'd still have the problem of handling the input generically. You'd need to inspect T just to figure out how many bytes to "parse" (and you're not really parsing…it's more of a byte-conversion/reinterpret cast operation, whereas "parse" typically refers to converting text to data).

You'll do much better to just follow the examples of the Convert, BitConverter, and BinaryReader classes, which include the type name in the method name itself. You need different implementations for each method anyway, and you know you need to specify the type name explicitly anyway, so just keep it simple.

Upvotes: 4

Related Questions