web-dev-qa-db-ja.com

複数の戻り型を持つメソッド

私はこれに似た多くの質問を調べてきましたが、私が正確に何をしたいのかについて実際に触れた質問はありませんでした。私がやろうとしていることは、外部ソースから、データ型も文字列配列に含む変数のリストを読み取ることです。

例:

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

たぶん私は何かを逃したかもしれませんが、私は本当にこのようなことを本当にする何かをまだ見つけていません。これに関するあらゆる考えも大歓迎です。

10
Free Radical

コンパイラーは、提供された3つのメソッド呼び出しを区別する方法がありません。これらはすべてMethod(key);のように見えるためです。

1つのオプションは、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値を追跡する必要はありません。

10

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/

7
Zenuka

関数の戻り値の型を入力する必要があります。他の変数または操作と同様に、指定されたタイプから継承するタイプは有効な戻り値です(そのため、オブジェクトは値としてすべてを許可します)。

個人的には、1つのメソッドを複数の戻り値の型で作成するのは便利だとは思いませんが、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;
    }

それが役に立てば幸い

0
Sneijder