简体   繁体   English

重载是向同一函数添加不同参数的唯一方法吗?

[英]Overload is the only way to add different parameter to the same function?

I have 2 functions that does the same exact operation; 我有2个函数执行相同的确切操作; since the underlying API has an overloaded fuction that accept either a string or an int. 因为基础API具有接受字符串或整数的重载函数。

Since I am using this function, I need to call the function either with a string or with an int. 由于我正在使用此函数,因此需要使用字符串或int调用该函数。 Is overloading the only way to do so? 超载是这样做的唯一方法吗? I replicate the code, beside the signature of the function; 我在函数签名旁边复制代码; and it seems a waste of code. 似乎浪费了代码。

public void taketwo(int value1, int value2)
{
    // Other operations happen here
    baseAPI.getvalues(value1, value2);
}

public void taketwo(string val1_str, string val2_str)
{
    // Other operations happen here
    baseAPI.getvalues(val1_str, val2_str);
}

I recall something about generic function; 我回想起有关泛型函数的内容; but I am not sure if that would apply in this case; 但我不确定在这种情况下是否适用; I never used them in the past, and before dive in, I thought that it was worth to ask around first. 我过去从未使用过它们,在潜入之前,我认为值得先问一下。

You could use dynamic typing here: 可以在此处使用动态类型输入:

// I don't recommend you do this - see later
public void TakeTwo(dynamic value1, dynamic value2)
{
    baseAPI.GetValues(value1, value2);
}

The overload resolution for the call to GetValues will then be performed at execution time. 然后将在执行时执行对GetValues的调用的重载解析。

However: 然而:

  • There's no compile-time checking that your call to TakeTwo will be valid 没有编译时检查您对TakeTwo的调用是否有效
  • It is less efficient (which may or may not be significant; the first point is more important in most cases) 它的效率较低(可能并不重要;在大多数情况下,第一点更重要)

You talk about replicating code, but in the example you've shown all the code is the method call. 您谈论的是复制代码,但是在示例中,您已经显示了所有代码都是方法调用。 If there's other code in the method which is genuinely common, I'd recommend extracting that common code out and calling it in both overloads: 如果该方法中还有其他真正通用的代码,则建议提取该通用代码并在两个重载中调用它:

public void TakeTwo(int value1, int value2)
{
    CommonCode();
    baseAPI.GetValues(value1, value2);
}

public void TakeTwo(string value1, string value2)
{
    CommonCode();
    baseAPI.GetValues(value1, value2);
}

private void CommonCode()
{
    // Things you want to do in both methods
}

Do int and string parameters represent different concepts? int和string参数代表不同的概念吗? If not, then you could code the implementation only once by calling 'string overload' from the 'int overload' 如果没有,那么您只能通过从“ int重载”中调用“ string重载”来编码一次实现

public void taketwo(int value1, int value2)
{
    taketwo(value1.ToString(), value2.ToString())
}

public void taketwo(string val1_str, string val2_str)
{
    // Other operations happen here
    baseAPI.getvalues(val1_str, val2_str);
}

This makes sense assuming there is more than just single API call in the methods. 假设方法中不仅有单个API调用,这是有道理的。

Here is my version of code to handle above scenario. 这是我处理上述情况的代码版本。 In my point of view it make sense to pass generic class instead of passing multiple parameter in function for flexibility. 以我的观点,为了灵活起见,传递通用类而不是传递函数中的多个参数是有意义的。

What if the api version got changed and need to handle third type like decimal. 如果api版本更改了并且需要处理第三种类型(如小数),该怎么办。

Below is the sample code which i though make it more flexible. 下面是示例代码,尽管我使它更加灵活。

    public class MyValues<T>
    {
        public T value1 { get; set; }
        public T value2 { get; set; }
    }

    public void TakeTwo<T>(MyValues<T> myvalue)
    {
        baseAPI.getvalues(myvalue.value1, myvalue.value2);
    }

To call TakeTwo for typeof(string) we can use something like below. 要为typeof(string)调用TakeTwo,我们可以使用类似下面的内容。

    TakeTwo<string>(new MyValues<string>() { value1 = "string 1", value2 = "string 2" });

To call TakeTwo for typeof(string) we can use something like below. 要为typeof(string)调用TakeTwo,我们可以使用类似下面的内容。

    TakeTwo<int>(new MyValues<int>() { value1 = 123, value2 = 345 });

Does it make sense? 是否有意义?

You could put the duplicate code - that you marked with // Other operations happen here - into its own method, if applicable. 您可以将重复的代码(用// Other operations happen here标记的// Other operations happen here )放入自己的方法中(如果适用)。 Obviously, this only would work, if this duplicate code doesn't make use of the passed in parameters. 显然,仅当此重复代码不使用传入的参数时,此方法才有效。


Generic methods can't be used here, because generics are a compile time feature, not a runtime feature. 泛型方法不能在这里使用,因为泛型是编译时功能,而不是运行时功能。 What you could do would be to use dynamic . 您可以做的就是使用dynamic In that case, the overload resolution would happen at runtime. 在这种情况下,过载解析将在运行时发生。 But it would have the disadvantage that you could also pass a double or Uri object and only at runtime you would get an exception, because no such overload exists for baseAPI.getvalues . 但这将带来一个缺点,即您还可以传递一个doubleUri对象,并且仅在运行时才能获得异常,因为baseAPI.getvalues不存在此类重载。

Code: 码:

public void taketwo(dynamic value1, dynamic value2)
{
    // Other operations happen here
    baseAPI.getvalues(value1, value2);
}

Depending on your baseAPI design you could use generics: 根据您的baseAPI设计,您可以使用泛型:

public void taketwo<T>(T val1, T val2)
{
    // Other operations happen here
    baseAPI.getvalues<T>(val1, val2);
}

but that would require making your baseAPI.getvalues generic in the first place. 但这首先需要使baseAPI.getvalues通用。

You can try to recieve an object (upcast), which means he will be able to send a string or int, and then with a simple if else you can send it to the correct function based on the value of that object. 您可以尝试接收一个对象(向上转换),这意味着他将能够发送字符串或整数,然后可以简单地将其发送给基于该对象值的正确函数。

public void taketwo(Object value1, Object value2) { 

// Other operations happen here 

If (check if value1 is a number) {
  baseAPI.getvalues(value1, value2); 
} else {
  baseAPI.getvalues(val1_str, val2_str);
}

Well, technically you can combine all this parameters into one method and set them having default parameter null . 好吧,从技术上讲,您可以将所有这些参数组合为一种方法,并将其设置为默认参数null

public void taketwo(int? value1 = null, int? value2 = null, 
                    string val1_str = null, string val2_str = null)
{
    if (value1 != null)
       baseAPI.getvalues(value1.Value, value2.Value);
    else if (val1_str != null)
       baseAPI.getvalues(val1_str, val2_str);
}

So you can call it as taketwo(1, 2) as well as taketwo(val1_str:"str1", val2_str:"str2") since all parameters has default values. 因此,您可以将其称为taketwo(1, 2)以及taketwo(val1_str:"str1", val2_str:"str2")因为所有参数都有默认值。

Will it be more convinient or not - it's up to you. 是否更方便-由您决定。 Personally I'd prefer method overloading rather than combining all possible parameters into one method. 我个人更喜欢方法重载,而不是将所有可能的参数组合成一个方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM