Set multiple return value for method declaration

I have a function as shown below:

public var UpdateMapFetcher(int stationID, int typeID) 

I need this function to return a string or int.

My return value is set below

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

How to have one data type as return value in a dynamic environment.

+6
source share
8 answers

My intuition tells me that you are trying to convert the value of a string to some type. In this case you can use:

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

If you don't know T, you can use matching (0-int, 1-string, etc.):

 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*/ } 

Another solution is to use implicit conversions:

 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 } 

And then (simplified):

 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 } 
+6
source

you can return the object. You will have to subsequently check the types in the consumption method. I assume this will not be a problem in your usecase.

your method signature:

 public object UpdateMapFetcher(int stationID, int typeID) 
+1
source

You also have the option of using the out keyword , which allows you to accept variables and check after calling the function.

 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) 

When using something like this:

 int intVal; string strVal; UpdateMapFetcher(stationID, typeID, out intVal, out strVal); if (strVal != null) { doSomethingWithString(strVal); } else { doSomethingWithInt(intVal); } 
+1
source

Frankly, I would just return a Tuple with a string that is not null indicating the value of the string to use, and null as an indicator to return int

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

Consumer side

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

I would choose to return the object new class , which might look like this:

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

This way you can check which one is Type using the Isxxx property. You can also improve this by validating the get value. F. e., For string it might look like this:

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

You cannot do just that, but there are several ways to do more or less of what you want. You are probably better off redesigning though.

Two ideas:

  • Either change your code to use two different methods, or call them as needed.
  • .. Or return an object that you can use as you like.
  • .. Or use a generic method with TypeDescriptor , as shown below.

Note that here we first convert the value to a string, even if it was an int, since we can use the general ConvertFromString() method to convert it to any type T

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

Using:

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

or

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

You can return the object and apply it to the type you want.

 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; } 
0
source

A type that can contain one or the other type is usually called (not surprisingly) Either . This is a special case such as a sum , mainly a discriminatory union, a labeled union or an incoherent union with exactly two cases (instead of an arbitrary number).

Unfortunately, there are no implementations of the Either type in standard libraries, but there are many implementations that can be found on Google, GitHub and other places ... and porting one of the existing implementations, for example. Haskell or Scala is also not so difficult.

This is a bit like this (forgive my code, I really don't know 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); } 

And you will use it as follows:

 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)); } } 
0
source

All Articles