C# 方法重载返回值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/937928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Method overloading return values
提问by charlieday
In C# I need to be able to define a method but have it return one or two return types. The compiler gives me an error when I try to do it, but why isn't it smart enough to know which method I need to call?
在 C# 中,我需要能够定义一个方法,但让它返回一两个返回类型。当我尝试这样做时,编译器给了我一个错误,但为什么它不够聪明,无法知道我需要调用哪个方法?
int x = FunctionReturnsIntOrString();
Why would the compiler prevent me from having two functions with different return types?
为什么编译器会阻止我使用两个具有不同返回类型的函数?
采纳答案by JaredPar
While it may be obvious in this particular scenario, there are many scenarios where this is in fact not obvious. Lets take the following API for an example
虽然在此特定场景中可能很明显,但在许多场景中这实际上并不明显。让我们以下面的 API 为例
class Bar {
public static int Foo();
public static string Foo();
}
It's simply not possible for the compiler to know which Foo to call in the following scenarios
编译器根本不可能知道在以下场景中调用哪个 Foo
void Ambiguous() {
Bar.Foo();
object o = Bar.Foo();
Dog d = (Dog)(Bar.Foo());
var x = Bar.Foo();
Console.WriteLine(Bar.Foo());
}
These are just a few quick samples. More contrived and evil problems surely exist.
这些只是一些快速示例。更人为、更邪恶的问题肯定存在。
回答by Andy White
The return type is not part of the method's signature, only the name and the parameter types. Because of this, you can't have two methods that only differ by the return type. One way to get around this would be for your method to return an object, then the calling code must cast it to either an int or string.
返回类型不是方法签名的一部分,只有名称和参数类型。因此,您不能有两种仅在返回类型上有所不同的方法。解决此问题的一种方法是让您的方法返回一个对象,然后调用代码必须将其转换为 int 或 string。
However, it might be better to create two different methods, or create a class to return from the method that can either contain an int or a string.
但是,最好创建两个不同的方法,或者创建一个类以从可以包含 int 或 string 的方法返回。
回答by Kane
Have you though about using generics to return the correct type.
您是否考虑过使用泛型返回正确的类型。
public T SomeFunction<T>()
{
return T
}
int x = SomeFunction<int>();
string y = SomeFunction<string>();
Note: This code has not been tested
注:此代码未经测试
回答by Arsen Mkrtchyan
In C# there is no overridin return types, IL supports that kind of overriding but C# not...yet.
在 C# 中没有覆盖返回类型,IL 支持这种覆盖,但 C# 不......还没有。
回答by jerryjvl
Because sometimes it really cannot tell which one it should then use (your example it could, but not all cases are that clear-cut):
因为有时它真的无法确定应该使用哪个(您的示例可以,但并非所有情况都那么明确):
void SomeMethod(int x) { ... }
void SomeMethod(string x) { ... }
In this context, if you call SomeMethod(FunctionReturnsIntOrString())
what should the compiler do?
在这种情况下,如果调用SomeMethod(FunctionReturnsIntOrString())
编译器应该怎么做?
回答by aJ.
Function differing only with return values do not qualify for the overloading.
仅返回值不同的函数不符合重载条件。
int x = FunctionReturnsIntOrString();
double y = FunctionReturnsIntOrString();
In the above case compiler can identify the correct functions but consider the cases in which return values are not specified, it is ambiguous.
在上述情况下,编译器可以识别正确的函数,但考虑到未指定返回值的情况,这是模棱两可的。
FunctionReturnsIntOrString(); //int version
FunctionReturnsIntOrString(); //double version
Compiler cannot resolve the overloaded methods here.
编译器无法解析这里的重载方法。
回答by Luke Schafer
I think you want to seriously reconsider what you're doing and how, but you CAN do this:
我认为您想认真地重新考虑您在做什么以及如何做,但您可以这样做:
int i = FunctionReturnsIntOrString<int>();
string j = FunctionReturnsIntOrString<string>();
by implementing it like this:
通过像这样实现它:
private T FunctionReturnsIntOrString<T>()
{
int val = 1;
if (typeof(T) == typeof(string) || typeof(T) == typeof(int))
{
return (T)(object)val;
}
else
{
throw new ArgumentException("or some other exception type");
}
}
but there are sooo many reasons not to.
但有很多理由不这样做。
回答by Timothy Carter
From the last paragraph of section 1.6.6 of the C# 3.0 language specification:
来自C# 3.0 语言规范第 1.6.6 节的最后一段:
The signature of a method must be unique in the class in which the method is declared. The signature of a method consists of the name of the method, the number of type parameters and the number, modifiers, and types of its parameters. The signature of a method does not include the return type.
方法的签名在声明该方法的类中必须是唯一的。方法的签名由方法的名称、类型参数的数量及其参数的数量、修饰符和类型组成。方法的签名不包括返回类型。
In IL two methods can differ by return type alone, but outside of reflection there is no means to call a method that differs only be return type.
在 IL 中,两种方法可以仅因返回类型而不同,但在反射之外,无法调用仅返回类型不同的方法。
回答by ebrown
You are also not required to assign a value to a called method. For example:
您也不需要为被调用的方法赋值。例如:
int FunctionReturnsIntOrString() {return 0;}
string FunctionReturnsIntOrString() {return "some string";}
//some code
//...
int integer = FunctionReturnsIntOrString(); //It probably could have figured this one out
FunctionReturnsIntOrString(); //this is valid, which method would it call?
回答by Philip Taron
it is possible to get the syntax you showed out in the question, but you have to engage in quite a good amount of cleverness in order to get there.
有可能获得您在问题中显示的语法,但您必须非常聪明才能到达那里。
Let's set up the problem a little more concretely. The key point here, I think, is the syntax. We want this:
让我们更具体地设置这个问题。我认为这里的关键点是语法。我们想要这个:
int intValue = GetData();
string stringValue = GetData();
DateTime[] dateTimeArrayValue = GetData();
However, we do not want this to work:
但是,我们不希望这样做:
double doubleValue = GetData();
DateTime? nullableDateTimeValue = GetData();
In order to accomplish this, we have to use an intermediary object in the return value from GetData()
, whose definition looks like this:
为了实现这一点,我们必须在 from 的返回值中使用一个中间对象GetData()
,其定义如下所示:
public class Data
{
public int IntData { get; set; }
public string StringData { get; set; }
public DateTime[] DataTimeArrayData { get; set; }
public MultiReturnValueHelper<int, string, DateTime[]> GetData()
{
return new MultiReturnValueHelper<int, string, DateTime[]>(
this.IntData,
this.StringData,
this.DataTimeArrayData);
}
}
Your implementation, of course, would be quite different, but this will do. Now let's define MultiReturnValueHelper
.
当然,您的实现会大不相同,但这会起作用。现在让我们定义MultiReturnValueHelper
.
public class MultiReturnValueHelper<T1, T2, T3> : Tuple<T1, T2, T3>
{
internal MultiReturnValueHelper(T1 item1, T2 item2, T3 item3)
: base(item1, item2, item3)
{
}
public static implicit operator T1(MultiReturnValueHelper<T1, T2, T3> source)
{
return source.Item1;
}
public static implicit operator T2(MultiReturnValueHelper<T1, T2, T3> source)
{
return source.Item2;
}
public static implicit operator T3(MultiReturnValueHelper<T1, T2, T3> source)
{
return source.Item3;
}
}
Repeat this definition for T1
, T2
, T3
, etc for the generic case.
对于一般情况T1
,对T2
、T3
、 等重复此定义。
You can also bind the return value helper very closely to the class or method that returns it, enabling you to create this same sort of effect for indexers, where you can get and assign a discrete set of types. That's where I've found it the most useful.
您还可以将返回值助手非常紧密地绑定到返回它的类或方法,使您能够为索引器创建这种相同的效果,您可以在其中获取和分配一组离散的类型。这就是我发现它最有用的地方。
Another application is to enable syntax like the following:
另一个应用程序是启用如下语法:
data["Hello"] = "World";
data["infamy"] = new DateTime(1941, 12, 7);
data[42] = "Life, the universe, and everything";
The precise mechanism to accomplish this syntax is left as an exercise to the reader.
完成此语法的精确机制留给读者作为练习。
For a more general-purpose solution to this problem (which is, I think, the same as a discriminated union problem), please see my answer to that question.
有关此问题的更通用的解决方案(我认为,这与有区别的联合问题相同),请参阅我对该问题的回答。