3

I apologize for the vague title but I wasn't really sure the best way to describe it.

I am writing a C# transform script in SSIS. The goal is to take in 5 values which are decimals, and I need to receive the first value out of 5 that is not null, in a predetermined order as you can see by the order of the else if statements. So as you can see I want to grab the MM value if it has one, if not then the PRE, then DD, PT, etc. You'll also see I just assign a little varchar label value to show which value came back as well.

Is there a cleaner/easier way of doing this that doesn't include a bunch of if/else if blocks? I'm just looking to clean it up.

current code below (Thanks for any advice!):

public Tuple<decimal?,string> getCurrentRec(Decimal? PT, Decimal? DD, 
Decimal? PRE, Decimal? MM)
{
    string ptlabel = "PT";
    string ddlabel = "DD";
    string prelabel = "PRE";
    string MMLabel = "MM";
    string curlabel;
    decimal? currentval;

    if (MM.HasValue)
    {
        curlabel = MMLabel;
        currentval = MM.Value;
    }

    else if (PRE.HasValue)
    {
        curlabel = prelabel;
        currentval = PRE.Value;
    }

    else if (DD.HasValue)
    {
        curlabel = ddlabel;
        currentval = DD.Value;
    }
    else if (PA.HasValue)
    {
        curlabel = ptlabel;
        currentval = PT.Value;
    }
    else
    {
        curlabel = "";
        currentval = (decimal?)null;
    }

    return Tuple.Create(currentval, curlabel);
}
user3494110
  • 417
  • 2
  • 9
  • 25
  • If a variable number of parameters to the method is acceptable, use a ``params`` array; otherwise, put the parameters into an array or list manually in the correct order, and iterate over it. – dumetrulo Feb 15 '18 at 15:15
  • 1
    `currentval = x ?? y ?? z ?? a;` If you want the name as well, create a data structure that represents a named value – Aluan Haddad Feb 15 '18 at 15:15
  • 3
    This might be better at [codereview.se], but read [this article before posting](https://codereview.meta.stackexchange.com/a/5778/13492). – Heretic Monkey Feb 15 '18 at 15:16
  • You do a x ?? y ?? z ?? ... to the number of parameters you have. Or accept the parameters as a params decimal array, then do a .FirstOrDefault(x => x.HasValue) on the array. If changing to params is not possible, you could add the parameters into an array yourself, then do FirstOrDefault(x => x.HasValue) – Tarek Feb 15 '18 at 15:20
  • If you have access to the SQL query itself, you can use a `coalesce` statement. – theMayer Feb 15 '18 at 15:45

2 Answers2

2

One possible way:

var match = new[] {
    new {v = MM, n = nameof(MM) },
    new {v = PRE, n = nameof(PRE) },
    new {v = DD, n = nameof(DD) },
    new {v = PT, n = nameof(PT) },
}.FirstOrDefault(c => c.v != null);
return Tuple.Create(match?.v, match?.n ?? "");

You create array of anonymous types with 2 properties: v for value of your decimal and n for corresponding label. Items in array should be in correct order. Then you use FirstOrDefault to find first element which has non null value.

Evk
  • 98,527
  • 8
  • 141
  • 191
0

Something like this might look neater:

public Tuple<decimal?,string> evaluate(Decimal? d, string s)
{
    if (!d.HasValue)
        return null;

    return Tuple.Create(d, s);
}
public Tuple<decimal?,string> getCurrentRec(Decimal? PT, Decimal? DD, Decimal? PRE, Decimal? MM)
{
    return evaluate(PT, "PT")
        ?? evaluate(DD, "DD")
        ?? evaluate(PRE, "PRE")
        ?? evaluate(MM, "MM")
        ?? Tuple.Create(null, null);
}
Steve Harris
  • 5,014
  • 1
  • 10
  • 25