How can I change this code in C # so that Visual Studio recognizes that I am not an idiot?

I have 3 lines that go

int selectedOrgId; 

foreach (Organization o in PD.orgs)
    if (o.orgname == selectedOrgName)
         selectedOrgId = o.orgid;

PD.cats.InsertOnSubmit(new Category {
    orgid = selectedOrgId,
    catname = newCatName
});

      

The middle line, the loop, is guaranteed in the context of my program to set the value for selectedOrgId

. However Visual Studio puts in the last line because

Using unassigned local variable 'selectedOrgId'

What is the way to solve this problem except

int selectedOrgId = 69; 

foreach (Organization o in PD.orgs)
    if (o.orgname == selectedOrgName)
         selectedOrgId = o.orgid;

PD.cats.InsertOnSubmit(new Category {
    orgid = selectedOrgId,
    catname = newCatName
});

      

????

Even though it works, it seems like an inelegant solution as it includes a magic number. I want to know the correct C # style to solve this question.

EDIT:

After looking at some of the discussions here, I had to point out that the database only has orgid

. My operator foreach

should have been written as

foreach (Organization o in PD.orgs)
{
    if (o.orgname == selectedOrgName)
    {
         selectedOrgId = o.orgid;
         break;
    }
 }

      

Thanks for showing me some of the best ways to do this!

+3


source to share


7 replies


It seems like you are iterating through the collection trying to find one matching value based on the organization name. You can use LINQ SingleOrDefault()

to find (at most) one match:

var selectedOrg = PD.orgs.SingleOrDefault(o => o.orgname == selectedOrgName);

      



Then only called InsertOnSubmit()

if the value found is: (otherwise selected Org will be null)

if (selectedOrg != null)
    PD.cats.InsertOnSubmit(new Category { orgid = selectedOrg.orgid, catname = newCatName });

      

+4


source


No .

What happens if the condition is o.orgname == selectedOrgName

not met for any value in PD.orgs

? Then it selectedOrgId

will remain uninitialized.

However, the following code may be more "elegant" according to your approach:



int selectedOrgId = PD.orgs.Single(o => o.orgname == selectedOrgName).orgid;
PD.cats.InsertOnSubmit(new Category { orgid = selectedOrgId, catname = newCatName });

      

Note that your code will install to the selectedOrgId

latest instance, while mine will assume that there is only one.

+3


source


You can use int?

:

int? selectedOrgId = null;

foreach (Organization o in PD.orgs)
{
    if (o.orgname == selectedOrgName)
    {
         selectedOrgId = o.orgid;
    }  
 }

 PD.cats.InsertOnSubmit(new Category 
 { 
        orgid = selectedOrgId,
        catname = newCatName 
 });

      

+2


source


Edit: The OP modified the question to indicate that only one item will be found and no multiple solution is required, here is Option 1a

Option 1a - One Linq Method

This provides a linq one line query that filters out unneeded organizations, grabs one item, and selects a new category object to be used as a parameter for your insert. This method will throw an exception if a single element cannot be located, but that is clearly what should happen depending on your question.

PD.cats.InsertOnSubmit(
    PD.orgs.Where(o=>o.orgname==selectedOrgName)
    .Single()
    .Select(o=>new Category { orgid = o.orgId, catname = newCatName })
);

      

Option 1b - Iterate the filtered list and get the job done

All other answers here suggest using linq and assume that only one entry will be found. Why not just do everything in a loop and use linq to filter the results?

foreach (Organization o in PD.orgs.Where(o=>o.orgname==selectedOrgName)) 
{
    PD.cats.InsertOnSubmit(new Category { orgid = o.orgId, catname = newCatName });
}

      

The catch here is no if statements and it handles one or more cases. There is a way to do this on one line and remove the explicit for each and use List.ForEach ( see Comparisons ):

PD.orgs.Where(o=>o.orgname==selectedOrgName).ToList()
.ForEach(o=>PD.cats.InsertOnSubmit(new Category { orgid = o.orgId, catname = newCatName }));

      

Option 2 - use an exception

This will let you know what your intentions are for the code and let Visual Studio know that you've taken care of it. The idea is to keep the code very close to how it is now:

int selectedOrgId; 
foreach (Organization o in PD.orgs) 
{
    if (o.orgname == selectedOrgName) 
       selectedOrgId = o.orgid;
}

      

However, at this point, I would suggest using an exception like:

if(selectedOrgId == 0) throw new InvalidDataException("Selected Org Id cannot be 0");
PD.cats.InsertOnSubmit(new Category { orgid = selectedOrgId, catname = newCatName });

      

+2


source


This is not the only problem. You know you will find 1 or more matches, the compiler doesn't know.

But the problem "or more" is also a problem. The code just isn't clear what you want, what's the reason. You have an implied "last win" strategy.

When you use a solution that meets the requirement more closely, the compiler problem goes away without any hacks.

Without Linq:

// int selectedOrgId; 

foreach (Organization o in PD.orgs)
    if (o.orgname == selectedOrgName)
    {
       PD.cats.InsertOnSubmit(new Category {
         orgid = o.orgid,
         catname = newCatName
      }); 
      return;   // or break;
    }
// shouldn't get here
throw new ...

      

And with Linq

Organization org =  PD.orgs.Single(o => o.orgname == selectedOrgName);
PD.cats.InsertOnSubmit(new Category {
          orgid = selectedOrgId,
          catname = newCatName
       }); 

      

The method is Single(Predicate)

fully consistent with your problem. It will throw when the result set has! = 1 element.

+2


source


Use linq to select an organization with selectedOrgName

and get orgid

:

PD.cats.InsertOnSubmit(new Category { 
    orgid = PD.orgs.First(o => o.orgname == selectedOrgName).orgid, 
    catname = newCatName
});

      


Assumes it selectedOrgName

will always be in PD.orgs

, and I am making this assumption based on the variable name; however, if this is not always the case, you can do the following:

var selectedOrg = PD.orgs.FirstOrDefault(o => o.orgname == selectedOrgName);

if (selectedOrg != null)
{
    PD.cats.InsertOnSubmit(new Category { 
        orgid = selectedOrg.orgid, 
        catname = newCatName
    });
}

      

+1


source


Below is the exact equivalent of what your code does, but it will throw an exception if you ever don't have an appropriate organization (which, as you say, cannot happen):

PD.cats.InsertOnSubmit(new Category { 
    orgid = PD.orgs.Last(o => o.orgname == selectedOrgName).orgid, 
    catname = newCatName
});

      

+1


source







All Articles