4

I created the function of c# to compare the price in my project.

public static decimal? SpecialPrice(decimal w, decimal p)
{
    if (w < p)
    {
        return p;
    }
    else if (w > p && p > 0)
    {
        //return (w , p);
    }
    else
    {
        return w;
    }
}

I want to return two variable ( w and p) when w > p and p >0 , but I don't know how can I return like that. Anyone know about it?

Mun
  • 14,098
  • 11
  • 59
  • 83
Nothing
  • 2,644
  • 11
  • 64
  • 115
  • 4
    Please, pick a style for your curly braces and make it consistent. – Steve Wellens Dec 20 '11 at 03:31
  • 2
    possible duplicate of [Is it possible for a function to return two values?](http://stackoverflow.com/questions/2434222/is-it-possible-for-a-function-to-return-two-values) – Jon Hanna Dec 20 '11 at 03:43
  • What is confusing about this logic is if `w` and `p` are treated like both input and output parameters. – John Alexiou Mar 15 '12 at 13:07

8 Answers8

9

Your choices for returning multiple values to calling code are:

  1. Out params
  2. Ref params
  3. Return a struct/object that contains multiple values, or another type like a collection

Basically, #1 and #2 let you have method arguments that let you pass values back to the calling code. See here for examples & reference:

http://msdn.microsoft.com/en-us/library/ee332485.aspx (out params)

http://msdn.microsoft.com/en-us/library/14akc2c7.aspx (ref params)

For #3, you would use a return value different from decimal?. For example, you could declare a class with two properties and return an instance of that. Or return a List<decimal> or some other type that can hold multiple values.

It's not really clear to me what the intent of your code is, so you'll need to decide which approach is best for you.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
JohnD
  • 14,327
  • 4
  • 40
  • 53
7

In C# you can not return two values from methods. It's better two return an array or some collection type which allows to hold more values than one.

Maybe something like this:

public static decimal[] SpecialPrice(decimal w, decimal p)
{
   if (w < p)
   {
      return new decimal[] { p };
   }
   else if(w > p && p > 0)
   {
       return new decimal[] { w, p };
   }
   else
   {
       return new decimal[] { w };
   }
}

If it's important to know which value is which after this method executes, you could use more sophisticated collection classes like the Dictionary class which lets you refer to each of its values by name.

I wouldn't create a new struct or class in this situation as I think the array size is a really easy indication of how many values are being returned where classes and structs will have the same number of variables before calling this method and after, making it harder to tell how many values were returned.

Roman
  • 10,309
  • 17
  • 66
  • 101
  • Specifying the array size is redundant when using a collection initializer (unless you want to get a compile error if you accidentally specify the wrong number of items). – Kevin Stricker Dec 20 '11 at 03:39
  • @mootinator, you're probably right. I've just wrote this without testing. I'll correct it. – Roman Dec 20 '11 at 03:42
  • 2
    @socheata: You really don't need to leave a "+1 thanks for your answer" comment to everyone's answer. Just click the +1 button; they can tell that their answer has been upvoted. It's standard around here to assume that means "thanks, this answer was useful". Adding comments like this all over the place just clutters things up. – Cody Gray - on strike Dec 20 '11 at 04:49
7

You could use a Tuple:

public static Tuple<decimal?, decimal?> SpecialPrice(decimal w, decimal p)
{
   if (w < p)
   {
      return new Tuple<decimal?, decimal?>(p, null);
   }
   else if(w > p && p>0)
   {
      return new Tuple<decimal?, decimal?>(p, w);
   }
   else
   {
      return new Tuple<decimal?, decimal?>(w, null);
   }
}
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
plmw
  • 321
  • 1
  • 8
  • `Tuple.Create(p, (decimal?)null);` would be (slightly) less cumbersome. – Kevin Stricker Dec 20 '11 at 03:48
  • @plmw : I tried that, but the result is contain (,), how can I display the result avoid this format? – Nothing Dec 20 '11 at 05:53
  • @socheata Are you wanting to use .ToString() to display the price? If so, you should be picking out the first value using tuple.Item1.ToString(). What are you wanting to display when you are returning both w and p though? – plmw Dec 20 '11 at 07:24
  • I want to line-through the w and display the p. – Nothing Dec 20 '11 at 07:59
  • @socheata Then flip the w and p around (I've made the edit in my answer), always print out the first item: tuple.Item1, and if tuple.Item2 != null, then print that out with line-through. – plmw Dec 20 '11 at 20:12
1

You can't have it return more than one object. However, you can just make the object that you return more complex.

public struct PandW
{
   public decimal? p{get;set;}
   public decimal? w{get;set;}
}

Then change your method to return PandW object:

 public static PandW SpecialPrice(decimal w, decimal p)
 {
 PandW temp;
if (w < p)
{
  temp.w=null;
  temp.p=p;
  return temp;
}else if(w > p && p>0){
   temp.w=w;
  temp.p=p;
  return temp;
}else{
   temp.w=w;
   temp.p=null;
   return temp;
}

}

Rondel
  • 4,811
  • 11
  • 41
  • 67
1

There are several ways to return multiple values:

  • You can create a class or a struct with multiple fields, and return an instance from your method
  • You can add output parameters to your method
  • You can return an array
  • You can return a KeyValuePair (not recommended)

In this particular case, I would prefer the first way to return two values:

class PriceRet {
    decimal? w;
    decimal? p;
}
PriceRet SpecialPrice(decimal w, decimal p) {
    var res = new PriceRet();
    if (w < p) {
        res.p = p;
    } else if(w > p && p>0) {
        res.w = w;
        res.p = p;
    } else {
        res.w = w;
    }
    return res;
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Try KeyValuePair<decimal,decimal>(w,p) but you need to change your return type to KeyValuePair.

Hope that helps.

T.Rob
  • 31,522
  • 9
  • 59
  • 103
Syed
  • 11
  • 1
1

That's why structures where invented

public struct PricePoints
{
    decimal? w, p;

    public PricePoints SpecialPrice()
    {
        PricePoints res;
        if (w < p)
        {
            res.p = p;
            res.w = null;
        }
        else if (w > p && p > 0)
        {
            res = this;
        }
        else
        {
            res.w = w;
            res.p = null;
        }
        return res;
    }
}
John Alexiou
  • 28,472
  • 11
  • 77
  • 133
0

the best way is to return object that has two properties, and also you can use the out variable

public static testhelper SpecialPrice(decimal w,decimal p)
{

//set your values in the object 
var Obj=new testhelper{
w=some value,
p= some value 
};
//// your code 

  if (w < p)
 {
   return p;
 }else if(w > p && p>0){
   //return (w , p);
 }else{
   return w;

} return Obj; }

public class testhelper{
  public int p{get;set;}
  public int w{get;set;}
 }
Abdallah
  • 62
  • 3
  • Out is just a horrible solution to anything, it breaks the OOP concept of scope and should alays be avoided if there are any other options – TravisO Feb 05 '21 at 16:10