0

I'm trying to return multiple values from a function in which I pass a parameter and store it in variable ZDO_S

In variable ZDO_S I'm trying to store two values which I will get by passing single value 'row["TVM_LS_NO"].ToString()' which is obtain from database in 'getdo' function

var ZDO_S = getDo(row["TVM_LS_NO"].ToString());

Here is the method :

private static (string TVD_LS_NO, string TVD_INV_NO) getDo(string DoNo)
{           
    try
    {
        using (OracleConnection con = new OracleConnection(ConfigurationManager.ConnectionStrings["Oracle_To_Sql.Properties.Settings.Setting"].ToString()))
        {
            string query = "select SUBSTR(TVD_DO_ITEM_NO,'1','10') from T_VEHICLE_DTL1  where TVD_LS_NO=:TVD_LS_NO";
            OracleCommand myCommand = new OracleCommand(query, con);
            DataTable dt = new DataTable();
            OracleDataAdapter da = new OracleDataAdapter(myCommand);
            da.SelectCommand = new OracleCommand(query, con);                    
            da.Fill(dt);                    

            foreach (DataRow row in dt.Rows)
            {
                string TVD_LS_NO = row["TVD_LS_NO"].ToString();
                string TVD_INV_NO = row["TVD_INV_NO"].ToString();                        
            }

            return (TVD_LS_NO, TVD_INV_NO);
        }
    }
    catch (Exception ex)
    {
        throw;
    }

}

Expected values should be return and stored in ZDO_S variable.

  1. actual getting error "cannot assign void to an implicitly-typed variable" at

    var ZDO_S=getDo(row["TVM_LS_NO"].ToString());
    
  2. IDentifier expected at

    private static (string TVD_LS_NO, string TVD_INV_NO) getDo(string DoNo)
    
  3. Since 'Program.getDo(String) returns void ,a return keyword must be followed by an object expression at

    return (TVD_LS_NO, TVD_INV_NO);
    
10
  • The syntax of the method signature looks correct, have you ensured that you're on C#7 or higher? Commented Jun 21, 2019 at 10:40
  • 6
    You're variables TVD_LS_NO and TVD_INV_NO are defined in the foreach block and therefore aren't visible at the point you do return. Commented Jun 21, 2019 at 10:40
  • 4
    As an aside, I'd strongly recommend that you start following .NET naming conventions, and avoid the redundant try/catch-then-throw block you've got here. Commented Jun 21, 2019 at 10:50
  • 1
    If it's not C#7, you cannot use this syntax. Tupels like this were added in C#7 so you'll have to fallback to the old tupels. They were defined like this Tupel<string, string>. They have the disadvantage of only having properties named "Item1" and "Item2" instead of the names you want but otherwise work in the same way. Commented Jun 21, 2019 at 11:08
  • 2
    I think if any method needs to return more than one value, defining a class/struct for it makes code more readable (except in cases like tryParse with out keyword, which is not very appealing for me either). Commented Jun 21, 2019 at 11:09

2 Answers 2

1

I'm not that familiar with C#, but if you want to return multiple values in a single return statement, the only way to go is usually an array or an object. An array would be simplest in your case.

  • The return type definition doesn't look like an array return type, try

private static string[] getDo() {...

  • The return statement itself doesn't look like an array, try returning the values as an array

  • You are defining variables inside the foreach-loop, which usually makes them unaccessible outside the loop. Try defining the variables outside the loop and use them in the loop.

I don't know if this is valid C#, but something like this:

private static String[] getDo(string DoNo)
    {           
        try
        {
            using (OracleConnection con = new OracleConnection(ConfigurationManager.ConnectionStrings["Oracle_To_Sql.Properties.Settings.Setting"].ToString()))
            {
                String[] toReturn = new String[2];
                string TVD_LS_NO, TVD_INV_NO;
                string query = "select SUBSTR(TVD_DO_ITEM_NO,'1','10') from T_VEHICLE_DTL1  where TVD_LS_NO=:TVD_LS_NO";
                OracleCommand myCommand = new OracleCommand(query, con);
                DataTable dt = new DataTable();
                OracleDataAdapter da = new OracleDataAdapter(myCommand);
                da.SelectCommand = new OracleCommand(query, con);                    
                da.Fill(dt);                    
                foreach (DataRow row in dt.Rows)
                {
                    TVD_LS_NO = row["TVD_LS_NO"].ToString();
                    TVD_INV_NO = row["TVD_INV_NO"].ToString();                        
                }
                toReturn[0] = TVD_LS_NO;
                toReturn[1] = TVD_INV_NO;
                return toReturn;
            }
        }
        catch (Exception ex)
        {

            throw;
        }

    }

Not sure if this will be the best answer, but I hope it will push you in the right direction.

Sign up to request clarification or add additional context in comments.

2 Comments

That is an idea, however it's not using the tupels which bring some nice features with them like you know exactly where the values are, you can name them, you can have different types, etc.
Then this way of doing it is probably not the best in his use case (but it is primitive and simple if you don't need those features, I guess).
0

There are a few concerns here, let's try to take them one by one.

  • First of all, you say you want to return two values, but you are assigning them in a for loop, which could mean they will be assigned many times. Is this on purpose ? Or are you expecting the for loop to run only once ?

  • Then, you declare your variables inside your for loop, which means they will be destroyed when you exit the loop, loosing their values and making the compiler angry (and sad).

  • You are trying to use a return result syntax that is known by compilers since C# 7. If you are using a prior version, it will not work at all.

  • Lastly, your try/catch is completely useless if you don't do something in your catch block, so you can remove it.

If I may suggest some additional understanding on TUples.

So, if we scratch it up in C# 7, it looks like this :

private static (string TVD_LS_NO, string TVD_INV_NO) getDo(string DoNo)
{
    //We declare our return value(s)
    var toReturn(TVD_LS_NO: "", TVD_INV_NO: "");

    using (OracleConnection con = new OracleConnection(ConfigurationManager.ConnectionStrings["Oracle_To_Sql.Properties.Settings.Setting"].ToString()))
    {
        string query = "select SUBSTR(TVD_DO_ITEM_NO,'1','10') from T_VEHICLE_DTL1  where TVD_LS_NO=:TVD_LS_NO";
        OracleCommand myCommand = new OracleCommand(query, con);
        DataTable dt = new DataTable();
        OracleDataAdapter da = new OracleDataAdapter(myCommand);
        da.SelectCommand = new OracleCommand(query, con);                    
        da.Fill(dt);                    

        foreach (DataRow row in dt.Rows)
        {
            //We assign our return values
            toReturn.TVD_LS_NO = row["TVD_LS_NO"].ToString();
            toReturn.TVD_INV_NO = row["TVD_INV_NO"].ToString();                        
        }

        return toReturn;
}

But that works only in C# 7

If you don't use C# 7, you have other possibilities :

  1. Use ref keyword

    int value = 0;
    MyFunction(ref value);
    Console.WriteLine(value); //Outputs 10
    
    void MyFunction(ref int value)
    {
        value = 10;
    }
    
  2. Use out keyword

    int value;
    MyFunction(value);
    Console.WriteLine(value); //Outputs 10
    
    void MyFunction(out int value)
    {
        value = 10;
    }
    

    To get the difference between the two, additional reading. You can use any number of ref/out parameters as you like.

  3. Use a small class/structure (preferred way)

    public struct MyResultValues //could be public class MyResultValues
    {
        public int result1;
        public string result2;
    }
    
    MyResultValues result = MyFunction();
    Console.WriteLine(result.result1);
    Console.WriteLine(result.result2);
    
    public MyResultValues MyFunction()
    {
        MyResultValues toReturn = new MyResultValues();
        toReturn.result1 = 10;
        toReturn.result2 = "Hello World !";
        return toReturn;
    }
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.