views:

399

answers:

5

I have a method that I'm writing that is calling another overloaded method inside it. I'd like to only write one outer method, since the parameter to the outer method is being passed to the inner one. Is there a way to do this?

I tried using generics, but I don't know enough about this so it isn't working:

public void OuterMethod<T>(T parameter)
{
    InnerMethod(parameter); // InnerMethod accepts an int or a string
}

I know that I can do this:

public void OuterMethod(string parameter)
{
    InnerMethod(parameter);
}

public void OuterMethod(int parameter)
{
    InnerMethod(parameter);
}

But I'd rather do this the right way instead of copying/pasting code. What's the best way to accomplish this?

+4  A: 

You can do this in C++ but not in C# (unless the inner method can also be generic instead of overloaded).


Alternatively (if you won't take 'no' for an answer), you can do a run-time switch on type, like for example ...

public void OuterMethod(object parameter)
{
    if (parameter is int)
        InnerMethod((int)parameter);
    else if (parameter is string)
        InnerMethod((string)parameter);
    else
        throw new SomeKindOfException();
}

... but obviously this is a run-time, not a compile-time check.

But I'd rather do this the right way instead of copying/pasting code.

You can also write software to write your outer methods (e.g. using System.CodeDom classes) instead of writing them by hand, but this is probably more trouble than it's worth.

ChrisW
A: 

If OuterMethod always calls InnerMethod, and InnerMethod only accepts an int or string, then OuterMethod<T> doesn't make any sense.

If the only difference is that one calls InnerMethod(int) and the other calls InnerMethod(string) you could do something like this:

public void OuterMethod(string parameter)
{
    InnerMethodA(parameter);
}

public void OuterMethod(int parameter)
{
    InnerMethodA(parameter);
}

private void InnerMethodA(object parameter)
{
    // Whatever other implementation stuff goes here

    if (parameter is string)
    {
        InnerMethodB((string) parameter);
    }
    else if (parameter is int)
    {
        InnerMethodB((string) parameter);
    }
    else
    {
        throw new ArgumentException(...);
    }
}

private void InnerMethodB(string parameter)
{
    // ...
}

private void InnerMethodB(int parameter)
{
    // ...
}
Zack Elan
+2  A: 

Like the others said, you can't really do what you are trying to do and the option you stated in your question is the best bet.

You would actually have to convert the value if you use the generic. Otherwise you can downcast by accepting an Object as ChrisW suggests.

 public void OuterMethod<T>(T parameter) 
            {
                T temp = parameter;
                if (temp is string )
                    InnerMethod(Convert.ToString(temp));
                if (temp is int)
                    InnerMethod(Convert.ToInt32(temp));// InnerMethod accepts an int or a string
            }

Here is a link to the overview of Generics: http://msdn.microsoft.com/en-us/library/ms172193.aspx

Jeff Martin
Just to add that for nullable types (string but not int) you can use the "as" keyword for your conversion.
Jacob Proffitt
You said, "you can't unbox it like ChrisW suggests" ... are you saying that you can't downcast, from object to int and/or from object to string? Note that my example `OuterMethod` isn't generic, and its parameter is of type `object` not of type `T`.
ChrisW
ahh right you are - my bad - i'll edit
Jeff Martin
A: 

From your description this seems like over-optimization.

How about:

public void OuterMethod(string parameter) { InnerMethod(parameter); }

public void OuterMethod(int parameter) { InnerMethod(parameter**.ToString()**); }

jro
A: 

Ok I have a similar situation, its an access control method in my business logic.

There is a save function that could be applied to any of my persistance layer objects.

so that looks like this

public static Save<T>(AccessControl.User user,T entity) where T:PersistanceLayerBaseClass
{
    if(CanWrite(user, entity))
    {
        entity.save();
    }
    else
    {
        throw new Exception("Cannot Save");
    }
}

How ever I have some custom code for certain entities in terms of Access Control so I wrote the following, it looks for a method more suitable to the question using System.Reflection, "can this entity be written by this user?"

public static Boolean CanWrite<T>(AccessControl.User user, T entity) where T : PersistanceLayerBaseClass
        {
            int? clubId = null;
            MethodInfo methodInfo = entity.GetType().GetMethod("CanWrite", new Type[] { typeof(AccessControl.User), entity.GetType() });
            if(methodInfo != null)
            {
                return (Boolean)methodInfo.Invoke(null, new object[] { user, entity }) ;
            }
            else 
            {
                //generic answer
            }
            return HasRole(user.UserID, "Administrator") || (clubId.HasValue && user.MemberObject.ClubId == clubId.Value && HasRole(user.UserID, "AdministerClub"));
        }

Now every time I add or remove a method, I only have to add or remove it in one place

Stephen lacy