为方法声明设置多个返回值

时间:2016-08-22 05:26:56

标签: c# methods svc

我有如下功能:

  public var UpdateMapFetcher(int stationID, int typeID)

我需要这个函数来返回string或int。

我的返回值设置如下

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

如何在动态环境中将一种数据类型作为返回值。

8 个答案:

答案 0 :(得分: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-string等):

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
}

然后(简化):

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 :(得分:1)

你可以返回一个物体。您必须随后检查您的消费方法中的类型。我认为在你的用例中不会出现问题。

因此您的方法签名是:

restaurantsJSONArray

答案 2 :(得分: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);
}

答案 3 :(得分:1)

坦率地说,我只返回一个元组,字符串为非空,表示要使用的字符串值,null为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);
    }

}

在消费者方面

var rc = UpdateMapFetcher( .... );

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

答案 4 :(得分:1)

我会选择返回object新的class,可能如下所示:

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

通过这种方式,您可以使用Type属性来检查Isxxx是哪个get。您还可以通过值string中的验证来增强此功能。 F. e。,对于public string StringValue { get { if (IsString) return m_stringValue; throw new InvalidOperationException("Value is not a string."); } } ,它可能看起来像这样:

input.replaceAll("(\"\\s*\"\\s*,?)", "");

答案 5 :(得分:1)

你真的不能完全,但有几种方法可以做更多或更少的你想要的。尽管如此,你可能会更好地改变设计。

两个想法:

  • 更改代码以使用两种不同的方法,并根据需要调用每种方法。
  • ..或者返回一个物体,你可以根据自己的喜好投射它。
  • ..或者,使用TypeDescriptor的通用方法,如下所示。

请注意,我们首先将值转换为字符串,即使它是一个int,因为我们可以使用公共方法ConvertFromString()将其转换为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);
    }
}

用法:

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

或:

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

答案 6 :(得分:0)

您可以返回Object并转换为您想要的类型。

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

答案 7 :(得分:0)

一种可以包含一种或另一种类型的类型通常被称为(不出所料)Either。这是sum type的一个特例,基本上是一个被区分的联合标记的联合,或不相交的联合恰好有两种情况(而不是任意数字。)

不幸的是,标准库中不存在Either类型的实现,但是在Google,GitHub和其他地方有很多实现......并且移植了一个现有的实现,例如: Haskell或Scala也不是那么难。

它看起来有点像这样(原谅我的代码,我实际上并不太了解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));
    }
}