-2

The question title might not be quite clear but here's what I want to do:

Say, I have a static class A. This class contains a static function called B. It has 10+ overloads. The function is pretty much basic in spite of so many overloads; it has nothing to do with other members of the class. I know I can access it from anywhere by importing the correct namespaces and using:

string bar = A.B("foo", true, 5) // Then do whatever with bar

Now, suppose I have another class C (Not in A). Now I want to make a method called D in C which behaves the same as A.B in all respects. I have tried:

public static class C {
    public static string D(string p1, bool p2, int p3) {
        return A.B(p1, p2, p3);
    }
}

But to overload this D method exactly like A.B, what do I have to do? Will I have to write all the separate overloads manually or is there a better way?

Fᴀʀʜᴀɴ Aɴᴀᴍ
  • 6,131
  • 5
  • 31
  • 52
  • 4
    If `C.D` "behaves the same as `A.B` in all respects" then what's the pint of `C.D`? – D Stanley Nov 04 '15 at 14:16
  • I know it's pointless but just for the sake of knowledge. Say I have five nested classes (I don't think there will ever be but still). I will have to access them by `AnIncrediblyLargeName.AnotherBigName.AnotherSubClass.YetAnotherSubClass.FinallyTheMethod`. So to access them from `C`, I was thinking of creating a method `D` so that I could simply call `D`. – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:20
  • 1
    I'm not following exactly, but static methods are not inherited, so there's no mechanism for inheritance or polymorphism of static methods. – D Stanley Nov 04 '15 at 14:27
  • That's what Imports is for, so that you don't need to write down all those namespace/class name everytime. Imports D = AnIncrediblyLargeName.AnotherBigName.AnotherSubClass.YetAnotherSubClass – the_lotus Nov 04 '15 at 14:33
  • @the_lotus Those things surrounded by dots in this case are classes, not namespaces. – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:34
  • You can still do it with classes. have you tried? – the_lotus Nov 04 '15 at 14:37
  • Oh yes you reminded me of `Imports SomeModule` which imports modules which are basically static classes but I don't think c# allows to import classes. – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:38
  • 1
    @the_lotus In addition to the OP's comment, it would also require writing such an alias on every single file using that type. – Servy Nov 04 '15 at 14:41

3 Answers3

3

Will I have to write all the separate overloads manually

If you want to have an overload of D for each overload of B, then yes, you'll have to do exactly that.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • Yes i thought so but each overload of D will also behave the same as the corresponding overload of B. Is there no possibility even then? – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:17
  • 1
    Or move all those methods into an interface/class to receive some compiler aid – Machinarius Nov 04 '15 at 14:18
  • @FarhanAnam There's no language support that would let you avoid it. You could write your own code generation tool (or find a 3rd party tool) to generate that code for you, but the code would still need to be written somehow. – Servy Nov 04 '15 at 14:20
  • I know it's pointless but just for the sake of knowledge. Say I have five nested classes (I don't think there will ever be but still). I will have to access them by `AnIncrediblyLargeName.AnotherBigName.AnotherSubClass.YetAnotherSubClass.FinallyTheMethod`. So to access them from `C`, I was thinking of creating a method `D` so that I could simply call `D`. – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:23
  • 1
    @FarhanAnam You could do that. You'll have to write out each overload. – Servy Nov 04 '15 at 14:32
  • @Yes, so to do that I was thinking of a simpler way than to write (or even generate) each overload. But since there's no way, there's no way. I have to accept this fact. Thanks for your help. – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:35
  • There is a way, if you are happy to forgo Intellisense and compile-time checking of D's parameters. See below. – mikeagg Nov 05 '15 at 10:43
  • 1
    @mikeagg Of course, he doesn't want to forgo either of those things. – Servy Nov 05 '15 at 13:48
-1

Why not make your basic method an extension method with a generic type and then simply implement any type-specific logic in the single extension method?

Payton Byrd
  • 956
  • 1
  • 12
  • 27
  • Why not stop answering without knowing that it's a situation not a code optimization question. – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 15:07
  • I thought this question was about how to use static methods in a repeatable way. Using extension methods with generics is by far the easiest way to implement repeatable techniques. It's not about code optimization, it's about understanding how statics, extensions and the basics of overloading. – Payton Byrd Nov 04 '15 at 15:26
  • Okay, but isn't it clear from the last two lines of my question? – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 15:27
  • And I'm telling you there's a better way. Use an extension method that accepts either A or D as a parameter. Then you don't need to duplicate your efforts. – Payton Byrd Nov 04 '15 at 15:36
-3

This is a good example of the drawbacks of static methods.

If you can, convert these static methods to instance methods (perhaps of some new worker class, with a static factory method to return the instance, or use IOC). Then you'll have much more flexibility to use inheritance to avoid repeating code.

UPDATE

After some feedback, I had a think and it is possible, kind of. Use reflection to get the parameter lists for all the versions of B, and compare with the parameter list of D.

public static int D(params object[] paramArray)
{
    var paramTypes = paramArray.Select(x => x.GetType());
    var method = typeof(Static.A).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy)
        .Where(m => m.Name == "B" && m.GetParameters().Select(x => x.ParameterType).SequenceEqual(paramTypes))
        .FirstOrDefault();
    if (method != null)
    {
        return (int)method.Invoke(null, paramArray);
    }
    throw new Exception("Overloaded method not found");
}

The downside of this approach is that there is no compile-time checking of parameters, no Intellisense, etc. I can't think of a way of getting round this without repeating the specification of each version of A.B(), like this:

    private static int GenericD(object[] paramArray, MethodBase caller)
    {
        var paramTypes = caller.GetParameters().Select(x => x.ParameterType);
        var method = typeof(Static.A).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy)
            .Where(m => m.Name == "B" && m.GetParameters().Select(x => x.ParameterType).SequenceEqual(paramTypes))
            .FirstOrDefault();
        if (method != null)
        {
            return (int)method.Invoke(null, paramArray);
        }
        throw new Exception("Overloaded method not found");
    }

    public static int D(string p)
    {
        object[] paramArray = new object[] { p };
        return GenericD(paramArray, MethodInfo.GetCurrentMethod());
    }

    public static int D(string p, int x)
    {
        object[] paramArray = new object[] { p, x };
        return GenericD(paramArray, MethodInfo.GetCurrentMethod());
    }

In this solution, each version of D() is almost identical, but not quite. Ideally you would want some way of programmatically converting a method's parameter list into an object[], but there doesn't seem to be an easy way to do that.

Community
  • 1
  • 1
mikeagg
  • 712
  • 3
  • 17
  • You didn't get the question I'm afraid. – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:32
  • I understood your question to be about how to avoid repeating a chunk of code. I pointed out that your options for avoiding repeating yourself are limited if you use static methods/classes. Is there any particular reason why you have chosen to make class A static, or to use nested classes? – mikeagg Nov 04 '15 at 14:41
  • I can't edit `A`. It is a class from another library. – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:42
  • I know it's pointless but just for the sake of knowledge. Say I have five nested classes (I don't think there will ever be but still). I will have to access them by AnIncrediblyLargeName.AnotherBigName.AnotherSubClass.YetAnotherSubClass.Finally‌​TheMethod. So to access them from C, I was thinking of creating a method D so that I could simply call D – Fᴀʀʜᴀɴ Aɴᴀᴍ Nov 04 '15 at 14:44