11

I have the following:

public static class CityStatusExt
{
    public static string D2(this CityStatus key)
    {
        return ((int) key).ToString("D2");
    }


public static class CityTypeExt
{
    public static string D2(this CityType key)
    {
        return ((int) key).ToString("D2");
    }

Plus other classes with similar extensions that return the key formatted as a "D2"

Is there a way I could inherit from a base class and have the base class provide the functionality so don't I don't have to repeat the same extension method code?

Update. I am sorry I did not mention this but my classes like CityType are Enums.

3 Answers3

8

You can make the method generic. C# will infer the type:

public static class Extension 
{ 
    public static string D2<T> (this T key) 
    { 
        return ((int)(object) key).ToString("D2"); 
    } 
}
JohnB
  • 13,315
  • 4
  • 38
  • 65
  • 5
    That won't compile as it is. You can't cast `T` to `int`. – phoog Oct 24 '12 at 06:23
  • I've edited it. Nevertheless, if you know what T will be, a where clause would make more sense. – JohnB Oct 24 '12 at 07:29
  • 2
    The types are enum types, however, so the where clause won't help. Also, the `(int)(object)key` cast will only work if the enum has the default underlying type of `int`. – phoog Oct 24 '12 at 07:40
4

From the comment below, CityType and CityStatus are enums. Therefore you can do this:

public static class Extensions
{
    public static string D2(this Enum key)
    {
        return Convert.ToInt32(key).ToString("D2");
    }
}

Original answer:

You can use a generic method and an interface ID2Able:

public static class Extensions
{ 
    public static string D2<T>(this T key) where T : ID2Able
    { 
        return ((int) key).ToString("D2"); 
    } 
}

This way the extension method won't show up for absolutely every type; it'll only be available for things you inherit ID2Able from.

lc.
  • 113,939
  • 20
  • 158
  • 187
  • Convert.ToInt32 risks losing information if the enum's underlying type is uint, long or ulong. – phoog Oct 24 '12 at 06:35
1

Your enums already all inherit from a common base class, namely System.Enum. So you can do this (Enums don't accept "D2" as a format string, but they accept "D", so I added a call to PadLeft):

public static class EnumExtensions
{
    public static string D2(this Enum e)
    {
        return e.ToString("D").PadLeft(2, '0');
    }
}
phoog
  • 42,068
  • 6
  • 79
  • 117
  • This is nice and easy, but slower than `Convert.ToInt32(key).ToString("D2")`, or `ToInt64` for that matter :) But that is of course only interesting if speed **really** is of the essence :) – flindeberg Oct 24 '12 at 07:03
  • @flindeberg did you profile it? How do you know it's slower? – phoog Oct 24 '12 at 07:15
  • I did @phoog, `e.ToString("D")` runs at 90% of the time of `Convert.ToInt64(e).ToString("D2")` but with the addition `PadLeft` it becomse slower by roughly 50%, ie `Convert.ToInt64(e).ToString("D2")` time factor 1, `e.ToString("D").PadLeft(2,'0')` with time factor 1.33. It really isn't that much of a deal unless speed **really** is of the essence and you are doing that conversion alot :) – flindeberg Oct 24 '12 at 07:27
  • @flindeberg The timing differences depend on whether the integer value is 1 character or more -- pad will return the same string if its length is >= the length argument. But still, I did some timings with 10 million iterations, and found that each iteration took around 0.41 microseconds with my slower code, and 0.36 microseconds with the faster code. So "a lot" is perhaps an understatement ;-) – phoog Oct 24 '12 at 07:36
  • @flindeberg try the `(int)(object)key` cast suggested in JohnB's edited answer. It's much faster indeed (but only works if you know that all your enums have `int` as their underlying type). – phoog Oct 24 '12 at 07:43
  • Indeed, that was fast :) 5 sec vs 3 sec for 10 000 000 iterations :) And as you said, pad got alot quicker when it didn't have to pad :) – flindeberg Oct 24 '12 at 09:01