views:

184

answers:

6

The root of my question is that the C# compiler is too smart. It detects a path via which an object could be undefined, so demands that I fill it. In the code, I look at the tables in a DataSet to see if there is one that I want. If not, I create a new one. I know that dtOut will always be assigned a value, but the the compiler is not happy unless it's assigned a value when declared. This is inelegant.

How do I rewrite this in a more elegant way?

             System.Data.DataTable dtOut = new System.Data.DataTable();
            .
            .
            // find table with tablename = grp
            // if none, create new table
            bool bTableFound = false;
            foreach (System.Data.DataTable d1 in dsOut.Tables)
            {
                string d1_name = d1.TableName;
                if (d1_name.Equals(grp))
                {
                    dtOut = d1;
                    bTableFound = true;
                    break;
                }
            }

            if (!bTableFound) dtOut = RptTable(grp);
+11  A: 

You can rewrite your method like so:

System.Data.DataTable dtOut = dsOut
                                   .Tables
                                   .Cast<System.Data.DataTable>()
                                   .FirstOrDefault(t => t.TableName.Equals(grp)) 
                                 ?? RptTable(grp);
Reed Copsey
This uses features I'm not familiar with: a learning opportunity.
SeaDrive
@SeaDrive: This is based on LINQ (for the cast + FirstOrDefault), and the null coalescing operator (??) to handle the null check. It replaces your entire method.
Reed Copsey
A: 
var dtOut = dsOut != null && dsOut.Tables != null && dsOut.Tables[grp] != null 
            ? dsOut.Tables[grp]
            : RptTable(grp);

HTH

Sunny
Why the -1 without any comment? Perhaps SO should enforce comments for down votes so that we can learn what went wrong...
Sunny
Fair point, Sunny. My guess is that the question is for C#, but your answer isn't.
Tim
Why is my code not c#?
Sunny
This is interesting, though I'm not sure I would call it elegant. I do not find expressions using the ? operator especially easy to read. I had not thought of doing "dsOut.Tables[grp] != null" would save doing the loop which is a good answer, but not to the question posed.
SeaDrive
+1  A: 
            ...program...
            {
               System.Data.DataTable dtOut = GetDataTableByName(grp, dsOut);
            }

            public DataTable GetDataTableByName(string grp, object dsOut)
            {
              foreach (System.Data.DataTable d1 in dsOut.Tables)
                {                    
                   if (d1.TableName.Equals(grp))
                     return RptTable(grp)
                }
              return null;
            }

If I've interperated your naming correctly.

runrunraygun
+11  A: 

That initial value can be null. The compiler doesn't require you to create an instance; it just requires you to assign a value.

System.Data.DataTable dtOut = null;  // compiler is now happy
// rest of code as before
itowlson
I think this is the easiest and most elegant way, and what I would have done.
Robo
This is probably the best answer at my level of programming complexity, but still seems inelegant to me. Fussy, fussy.
SeaDrive
A: 

I like Otávio's answer, but here's an alternate approach anyway. You can shove the foreach loop down into its own method, something like:

static System.Data.DataTable
getDataTable ( System.Data.DataTable[] tables, String grp )
{
    foreach (System.Data.DataTable d1 in tables)
        {
            string d1_name = d1.TableName;
            if (d1_name.Equals(grp))
            {
                return d1;
            }
        }
    return null;
}

This lets you simplify your original method to:

System.Data.DataTable dtOut = getDataTable(dsOut.Tables, grp);
if (!dtOut) dtOut = RptTable(grp);
Tim
A: 

If you want elegance, go LINQ:

var dtOut = 
  dsOut.Tables.FirstOrDefault(t => t.TableName == grp)
  ?? RptTable(grp);
Fábio Batista