重载方法调用重载方法

3

我正在编写一个方法,在该方法中调用另一个重载的方法。由于参数被传递到内部方法中,我想只编写一个外层方法。有没有办法做到这一点?

我尝试使用泛型,但是我对此不够了解,所以它不能正常工作:

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

我知道我可以做到这一点:

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

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

但我宁愿用正确的方法来完成这个任务,而不是复制/粘贴代码。那么最好的方法是什么?

6个回答

4

在C++中可以做到这一点,但在C#中不行(除非内部方法也可以是泛型而不是重载)。


或者(如果你不接受“不行”的答案),你可以根据类型进行运行时切换,例如...

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

...但显然这是一种运行时检查,而不是编译时检查。

但我宁愿以正确的方式完成这个任务,而不是复制/粘贴代码。

您还可以编写软件来编写您的外部方法(例如使用System.CodeDom类),而不是手动编写它们,但这可能比它值得的麻烦要多。


2

像其他人说的那样,你不能真正做到你试图做的事情,你在问题中提出的选项是最好的选择。

如果使用通用类型,则必须转换该值。否则,您可以通过接受对象来向下转换,就像ChrisW建议的那样。

 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
            }

这是一个泛型概述的链接:http://msdn.microsoft.com/en-us/library/ms172193.aspx

只是补充一下,对于可空类型(字符串但不包括整数),你可以使用 "as" 关键字进行转换。 - Jacob Proffitt
你说,“你不能像ChrisW建议的那样解包它”...你是说你不能将对象向下转换为int和/或string吗?请注意,我的示例OuterMethod不是通用的,它的参数类型是object而不是T类型。 - ChrisW

1
你可以使用 dynamic 类型来推迟重载解析直到运行时。
public void OuterMethod(dynamic parameter)
{
    InnerMethod(parameter);
}

public void InnerMethod(int parameter) { }
public void InnerMethod(string parameter) { }

注意:动态类型的表达式不会被编译器解析或类型检查。可能会导致性能下降。


1

根据您的描述,这似乎是过度优化。

那么怎么样:

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

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

0

好的,我有一个类似的情况,它是我的业务逻辑中的访问控制方法。

有一个保存函数可以应用于我的任何持久层对象。

所以看起来像这样

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

然而,对于某些实体的访问控制,我有一些自定义代码,因此我编写了以下代码,它使用System.Reflection查找更适合问题的方法,“此用户是否可以编写此实体?”

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"));
        }

现在每次我添加或删除一个方法,我只需要在一个地方添加或删除它。

0
如果OuterMethod总是调用InnerMethod,而InnerMethod只接受int或string类型的参数,那么OuterMethod<T>就毫无意义。
如果唯一的区别在于一个调用InnerMethod(int),而另一个调用InnerMethod(string),那么你可以尝试这样做:
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)
{
    // ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接