2016-08-22 24 views
6

ための複数の戻り値を設定します。は、以下のように私は機能を持っているメソッド宣言

私の戻り値は、動的な環境での戻り値として一つのデータ型のいずれかを持っている方

if (finaloutput == "System.String") 
     { 
      // param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string)); 
      returnvalue = returnvalue.ToString(); 
      return returnvalue; 
     } 
     else if (finaloutput == "System.Int32") 
     { 
      int a=0; 
      a = Convert.ToInt32(returnvalue); 
      return a; 
     } 

以下のように設定されています。

+0

ことができますそれがなぜあなたが必要なのかをよく説明してください。 (あなたはいつでも 'オブジェクト'を返すことができますが、ちょっとしたデザインを考え直すべきでしょう) –

+0

'var'はちょうど"コンパイラです。正しいデータ型を見つけてここに入れてください "。コンパイル時に*決定する必要があります*。 –

答えて

6

私の直感は、文字列の値をある種のものに変換しようとしていることを伝えています。

public T UpdateMapFetcher<T>(int stationID) 
{ 
    //var someValue = "23"; 
    return (T)Convert.ChangeType(someValue, typeof(T)); 
} 
//then 
var typed = UpdateMapFetcher<int>(6); 

あなたはTを知らない場合は、あなたが(など0-INT、1列、)マッピングを使用することができます:あなたが使用することができ、その場合には

public object UpdateMapFetcher(int stationID, int type) 
{ 
    var typeMap = new []{ typeof(int), typeof(string)}; 
    //var someValue = "23"; 
    return Convert.ChangeType(someValue, typeMap[type]); 
} 
//then 
var untyped = UpdateMapFetcher(6, 0/*0 is int*/); 
if (untyped.GetType() == typeof(int)) 
{ /*is int*/ 
} 

別の解決策は、暗黙的な変換を使用することです:

public class StringOrInt 
{ 
    private object value; 
    public ValueType Type { get; set; } 

    public static implicit operator StringOrInt(string value) 
    { 
     return new StringOrInt() 
     { 
      value = value, 
      Type = ValueType.String 
     }; 
    } 
    public static implicit operator StringOrInt(int value) 
    { 
     return new StringOrInt() 
     { 
      value = value, 
      Type = ValueType.Int 
     }; 
    } 
    public static implicit operator int(StringOrInt obj) 
    { 
     return (int)obj.value; 
    } 
    public static implicit operator string(StringOrInt obj) 
    { 
     return (string)obj.value; 
    } 
} 
public enum ValueType 
{ 
    String, 
    Int 
} 

そして(simplifie D):

public static StringOrInt UpdateMapFetcher(int stationID, int typeID) 
{ 
    if (typeID == 0) 
     return "Text"; 
    return 23; 
} 

private static void Main(string[] args) 
{ 
    var result = UpdateMapFetcher(1, 1); 
    if (result.Type == ValueType.String) { }//can check before 
    int integer = result;//compiles, valid 
    string text = result;//compiles, fail at runtime, invalid cast  
} 
1

オブジェクトを返すことができます。その後、消費メソッドでタイプをチェックする必要があります。私はそれがあなたのユースケースには問題ではないと考えています。

あなたのメソッドのシグネチャは、そのためです:

public object UpdateMapFetcher(int stationID, int typeID) 
0

オブジェクトを返し、あなたが望むどの型にキャストすることができます。

public Object UpdateMapFetcher(int stationID, int typeID) 

if (finaloutput == "System.String") 
     { 
      // param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string)); 
      returnvalue = returnvalue.ToString(); 
      return returnvalue; 
     } 
     else if (finaloutput == "System.Int32") 
     { 
      int a=0; 
      a = Convert.ToInt32(returnvalue); 
      return a; 
     } 
1

はまた、あなたは両方の変数に受け入れて、関数が呼び出された後に確認することが可能out keywordを、使用するオプションがあります。

public void UpdateMapFetcher(int stationID, int typeID, out int intValue, out string strValue) 

// or int return val and out string value 

public int UpdateMapFetcher(int stationID, int typeID, out string strValue) 
このような何か表示されて使用して

:率直に言って

int intVal; 
string strVal; 

UpdateMapFetcher(stationID, typeID, out intVal, out strVal); 

if (strVal != null) 
{ 
    doSomethingWithString(strVal); 
} 
else 
{ 
    doSomethingWithInt(intVal); 
} 
1

、私は単なる文字列は、文字列値を使用することを示すnull以外のもので、タプルを返しますが、int型のリターンのための指標としてnull消費者側では

public Tuple<string, int> UpdateMapFetcher(int stationID, int typeID) { 
    if (finaloutput == "System.String") 
    { 
     // param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string)); 
     returnvalue = returnvalue.ToString(); 
     return new Tuple<string, int>(returnvalue, 0); 
    } 
    else if (finaloutput == "System.Int32") 
    { 
     int a=0; 
     a = Convert.ToInt32(returnvalue); 
     return new Tuple<string, int>(null, a); 
    } 

} 

var rc = UpdateMapFetcher(....); 

if (rc.Item1 != null) { 
    // code to use string value 
} else { 
    // code to use int value 
} 
1

私はこのようになります新しいclassobject返すために選ぶだろう:あなたはそれがIsxxxプロパティを使用して、あるType確認することができ

class Result { 

    public string StringValue { get; } 

    public string Int32Value { get; } 

    public bool IsString { get; } 

    public bool IsInt32 { get; } 

    public Result(string value) { 
     StringValue = value; 
     IsString = true; 
    } 

    public Result(int value) { 
     Int32Value = value; 
     IsInt32 = true; 
    } 
} 

この道を。値get ersの検証でこれを強化することもできます。 F.、stringのためには、次のようになります。あなたは本当に正確に多かれ少なかれ、あなたがやりたいことには、いくつかの方法がありますが、をを行うことはできません

public string StringValue { 
    get { 
     if (IsString) 
      return m_stringValue; 
     throw new InvalidOperationException("Value is not a string."); 
    } 
} 
1

。あなたはおそらくデザインを少し変更する方が良いでしょう。

つのアイデア:

  • いずれかの二つの異なる方法を使用するようにコードを変更し、代わりに、必要に応じてそれらのそれぞれを呼び出します。
  • ..オブジェクトを返すか、好きなだけキャストすることができます。
  • ..またはTypeDescriptorという一般的な方法を使用します。

だった私たちは、その後どのようなタイプTに変換する一般的な方法ConvertFromString()を使用することができますので、我々はここで、それはint型であっても最初の値を文字列に変換するに注意してください。

public T UpdateMapFetcher<T>(int stationID, int typeID) { 
    // To allow parsing to the generic type T: 
    var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)); 
    if(converter != null) 
    { 
     return (T)converter.ConvertFromString(returnvalue.ToString()); 
    }  
    else 
    { 
     return default(T); 
    } 
} 

使用:

var result = MyExtensions.UpdateMapFetcher<string>(1, 2); 

または:

var result = MyExtensions.UpdateMapFetcher<int>(1, 2); 
0

タイプ一種または別のいずれかを含むことができ、通常は(当然)Eitherと呼ばれています。これはsum typeの特別な場合、基本的に判別組合タグ付けされた組合、または正確に2例(代わりに、任意の数)と互いに素組合あります。

残念ながら、標準ライブラリにはEitherタイプの実装は存在しませんが、Google、GitHubなどには多数の実装があります。ハスケルやスカラもそれほど難しくありません。

それは少しこのようになります(私のコードを許して、私は実際にC♯よく知っていない)を:

using System; 

abstract class Either<A, B> 
{ 
    public abstract bool IsLeft { get; } 
    public abstract bool IsRight { get; } 
    public abstract A Left { get; } 
    public abstract B Right { get; } 
    public abstract A LeftOrDefault { get; } 
    public abstract B RightOrDefault { get; } 
    public abstract void ForEach(Action<A> action); 
    public abstract void ForEach(Action<B> action); 
    public abstract void ForEach(Action<A> leftAction, Action<B> rightAction); 

    private sealed class L : Either<A, B> 
    { 
     private A Value { get; } 
     public override bool IsLeft => true; 
     public override bool IsRight => false; 
     public override A Left => Value; 
     public override B Right { get { throw new InvalidOperationException(); } } 
     public override A LeftOrDefault => Value; 
     public override B RightOrDefault => default(B); 
     public override void ForEach(Action<A> action) => action(Value); 
     public override void ForEach(Action<B> action) {} 
     public override void ForEach(Action<A> leftAction, Action<B> rightAction) => leftAction(Value); 

     internal L(A value) { Value = value; } 
    } 

    private sealed class R : Either<A, B> 
    { 
     private B Value { get; } 
     public override bool IsLeft => false; 
     public override bool IsRight => true; 
     public override A Left { get { throw new InvalidOperationException(); } } 
     public override B Right => Value; 
     public override A LeftOrDefault => default(A); 
     public override B RightOrDefault => Value; 
     public override void ForEach(Action<A> action) {} 
     public override void ForEach(Action<B> action) => action(Value); 
     public override void ForEach(Action<A> leftAction, Action<B> rightAction) => rightAction(Value); 

     internal R(B value) { Value = value; } 
    } 

    public static Either<A, B> MakeLeft(A value) => new L(value); 
    public static Either<A, B> MakeRight(B value) => new R(value); 
} 

そして、あなたはこのようにそれを使用したい:

static class Program 
{ 
    public static void Main() 
    { 
     var input = Console.ReadLine(); 
     int intResult; 
     var result = int.TryParse(input, out intResult) ? Either<int, string>.MakeLeft(intResult) : Either<int, string>.MakeRight(input); 
     result.ForEach(r => Console.WriteLine("You passed me the integer one less than " + ++r), r => Console.WriteLine(r)); 
    } 
} 
関連する問題