具有多个返回类型的方法

16

我查看了许多与此类似的问题,但没有一个真正涉及到我想要做的事情。我想要做的是从外部源读取包含它们的数据类型在内的变量列表,并将它们存储在一个字符串数组中:

例子:

ID/Key      Type    Value/Data; 
varName1    bool    true;
varName2    string  str;
varName3    int     5;

然后,我将这些对象作为包含多个字符串的对象存储在字典中,ID也用作键。

现在我想创建一个方法,使用switch语句将字符串转换为正确的数据类型,并返回它,无需在方法调用中指定任何内容。该函数应该类似于:

public ??? Method(string key)
{
    if(dictionary.ContainsKey(ID))
    {
        Var temp = dictionary[ID];

        switch (temp.Type)
        {
            case "bool":
                return Convert.ToBoolean(temp.Value);

            case "int"
                return Convert.ToInt(temp.Value);

            case "string"
                return temp.Value;
        }
    }

    return "NULL"; 
}

方法调用应该类似于这样:

int x = Method(string key);
string word = Method(string key);
bool isTrue = Method(string key);

也许我错过了什么,但我还没有找到像这样真正能做到这件事的东西。欢迎任何关于此的想法。


2
抱歉,在C#中没有这样的东西。方法具有固定的返回类型。您可以使用“object”作为返回类型,但必须进行强制转换。 - adv12
1
你需要将该方法泛型化才能使其工作。当你使用它时,它会变成 string word = Method<string>(key) 的样子。此外,你还需要使用 bool?int?,因为你想在未找到键时返回 null - juharr
如果您的值被存储为“Object”,则可以执行(T)value。如果方法返回“object”,那么为什么不使用string word = (string)Method(string key);呢? - T.S.
2
你打算如何处理该方法的返回值? - Anton Gogolev
我真的认为,你需要 public IKnowHowToconvertData Method<T>(string key) - T.S.
显示剩余2条评论
3个回答

21
在C# 7中,您可以选择像这样从方法中返回多个值:
public (string SomeString, int SomeInt) DoSomething() { ... }
您可以这样获取值:
var result = DoSomething();
Console.WriteLine(result.SomeString);
Console.WriteLine(result.SomeInt.ToString());
或者
(var someString, var someInt) = DoSomething();
Console.WriteLine(someString);
Console.WriteLine(someInt.ToString());

这个操作使用元组在底层进行,你不仅限于只返回2个值。我不知道你可以返回多少个值,但是当你需要返回那么多的值时,我建议创建一个类。

更多信息:https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/


17

更新

我相信很多人来到这个问题是因为他们想要一般地返回多个值,而不一定是在原始问题中给出的目的。如果这是您想要的,有几种选择可供选择。

如果您返回的类型组合表示一个可能在方法调用之外有用的概念,请考虑创建一个表示该概念的类型。C#的记录提供了一种漂亮、简洁的方式来实现这一点:

public record ExtractedValue(bool? BooleanValue, string? StringValue, int? IntValue);

public ExtractedValue Method(string key)
{
   ...
}

如果这些值只会在这个地方一起出现,而且不值得想出一个命名类型来表示这些值,你也可以使用值元组。但是请注意,如果您计划将该类型用于序列化之类的操作,可能会有一些行为上的影响。
public (bool? BooleanValue, string? StringValue, int? IntValue) Method(string key)
{
   ...
}

原始回答

编译器无法区分您提供的三个方法调用之间的区别,因为它们看起来都像 Method(key);

一种选择是返回一个 object,然后期望使用代码将其转换为他们想要的类型:

public object Method(string key)
{
    if(dictionary.ContainsKey(key))
    {
        var temp = dictionary[key];

        switch (temp.Type)
        {
            case "bool":
                return Convert.ToBoolean(temp.Value);

            case "int"
                return Convert.ToInt(temp.Value);

            case "string"
                return temp.Value;
        }
    }

    return "NULL"; 
}

...

int x = (int) Method(key);
string word = (string) Method(key);
bool isTrue = (bool) Method(key);

你也可以使用 dynamic 关键字使转换隐式化:
public dynamic Method(string key)
{
    if(dictionary.ContainsKey(key))
    {
        var temp = dictionary[key];

        switch (temp.Type)
        {
            case "bool":
                return Convert.ToBoolean(temp.Value);

            case "int"
                return Convert.ToInt(temp.Value);

            case "string"
                return temp.Value;
        }
    }

    return "NULL"; 
}

...

int x = Method(key);
string word = Method(key);
bool isTrue = Method(key);

然而,“动态”是一个非常强大的概念,很容易失控,因此您必须非常小心。看起来你期望调用代码知道每个键所期望得到的对象类型。也许最好的方法是让用户提供这些信息:
public T Method<T>(string key)
{
    if(dictionary.ContainsKey(key))
        return (T) Convert.ChangeType(dictionary[key].Value, typeof(T));
    return default(T);
}

...

int x = Method<int>(key);
string word = Method<string>(key);
bool isTrue = Method<bool>(key);

这样的话,在你的字典对象中就不需要追踪 Type 值了。

1
我意识到原帖使用了 boolean,但在 C# 中应该使用 boolBoolean - juharr
同样地,从 OP 来看,在 C# 中 Var 是无效的,应该使用 var - Frédéric
Var是我用来存储从文件中读取的内容的类名,而在整个bool/boolean/Boolean的事情上,我只是凭记忆大致操作。 - Free Radical
动态关键字可以使用,但我刚想起自己被限制在了3.5框架下,因为动态仅支持4.0版本以上。 - Free Radical
1
@FreeRadical:好的,我给了你三个不同的选项,只有一个使用了dynamic,请告诉我其他两个选项为什么不能满足你的需求。另外,给一个类命名为“Var”是一个非常糟糕的想法。 - StriplingWarrior

-1
函数的返回类型必须有类型。与任何其他变量或操作一样,从指定类型继承的任何类型都是有效的返回值(这就是为什么对象允许任何值作为值)。
个人认为制作一个具有多个返回类型的方法并不实用,但如果您真的想要一个具有多个返回类型的方法,您可以在.NET 4.0中使用dynamic类型。
    private static void Main(string[] args)
    {
        int x = Method("varName3");
        string word = Method("varName2");
        bool isTrue = Method("varName1");
    }

    private static dynamic Method(string key)
    {
        var dictionary = new Dictionary<string, KeyValuePair<Type, object>>()
        {
            { "varName1", new KeyValuePair<Type, object>(typeof(bool), false) },
            { "varName2", new KeyValuePair<Type, object>(typeof(string), "str") },
            { "varName3", new KeyValuePair<Type, object>(typeof(int), 5) },
        };

        if (dictionary.ContainsKey(key))
        {
            return dictionary[key].Value;
        }

        return null;
    }

希望能有所帮助


1
非常有帮助,但不幸的是我只能使用3.5框架。背景:这是为使用Unity的人设计的工具。 - Free Radical
1
如果你只能使用.NET 3.5,我会尝试将该方法泛型化: int x = Method<int>("varName3");请查看StriplingWarrior的答案。 - Sneijder
1
喜欢 C# 可以让事情既静态又动态的特性。 - Alan B

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