【问题标题】:Method with Multiple Return Types具有多种返回类型的方法
【发布时间】:2016-04-20 07:34:41
【问题描述】:

我已经查看了许多与此类似的问题,但没有一个真正涉及到我究竟想要做什么。我要做的是从外部源读取变量列表,这些变量也将它们的数据类型包含到字符串数组中:

例子:

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

也许我错过了一些东西,但我还没有找到真正能做到这样的东西。也欢迎任何和所有关于此的想法。

【问题讨论】:

  • 对不起,C# 中没有这样的东西。方法具有固定的返回类型。您可以使用 object 作为您的返回类型,但您必须强制转换。
  • 您必须使该方法具有通用性才能使其正常工作。当你使用它时,它最终看起来像string word = Method<string>(key)。此外,您还必须执行bool?int?,因为您想在找不到密钥时返回null
  • 如果您的值存储为Object,您可以使用(T)value。是什么阻止了你 string word = (string)Method(string key);,给定,方法返回 object
  • dynamic 怎么样?
  • 你打算如何处理方法的返回值?

标签: c# generics methods return


【解决方案1】:

在 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());

这适用于 Tuple 的表面之下,并且您不仅限于 2 个值。我不知道你可以返回多少,但我建议当你需要返回那么多值时,创建一个类。 更多信息:https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/

【讨论】:

    【解决方案2】:

    编译器无法区分您提供的三个方法调用,因为它们看起来都像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);
    

    但是,dynamic 是一个非常强大的概念,它很容易失控,所以你必须非常小心。

    在我看来,您希望调用代码知道它希望为每个键获取哪种类型的对象。似乎最好的方法是让用户提供这些信息:

    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 值。

    【讨论】:

    • 我意识到 OP 使用了boolean,但在 C# 中它是 boolBoolean
    • 同样来自 OP,Var 在 C# 中无效,应为 var
    • Var 是我用来存储从文件中读取的内容的类的名称,我在整个 bool/boolean/Boolean 事物上松散地从内存中获取。
    • dynamic 关键字有效,但我只记得我仅限于 .3.5 框架,而 dynamic 仅限 4.0。
    • @FreeRadical:嗯,我给了你三个单独的选项,其中只有一个使用动态,所以如果有其他原因不适合你,请告诉我。而且,顺便说一句,将一个类命名为 Var 是一个非常糟糕的主意。
    【解决方案3】:

    必须输入函数的返回类型。与任何其他变量或操作一样,从指定类型继承的任何类型都是有效的返回值(这就是 object 允许任何值作为值的原因)。

    我个人认为创建一种具有多种返回类型的方法没有用,但如果您真的想要一种具有多种返回类型的方法,您可以在 .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;
        }
    

    希望对你有帮助

    【讨论】:

    • 帮助很大,但不幸的是我仅限于 3.5 框架。背景:这是一个供使用 Unity 的人使用的工具。
    • 如果您仅限于 .NET 3.5,我会尝试将方法设为通用:int x = Method("varName3");请看一下 StriplingWarrior 的回答。
    • 喜欢 C# 如何让事物既是静态的又是动态的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-09
    相关资源
    最近更新 更多