3
\$\begingroup\$

As the title states. I need a different type of icon for the different nodes types. at the moment I have this hacky way of achieving that.

for (var x = 0; x <= nodeList.Count - 1; x++)
{
     if (xNode.Attributes["TYPE"].Value == "server.point.AV")
     {
         var tNode2 = new TreeNode(xNode.Attributes["NAME"].Value, AnalogImagesIndex, AnalogImagesIndex);
         inTreeNode.Nodes.Add(tNode2);
         tNode2 = inTreeNode.Nodes[x];
         AddNode(xNode, tNode2);
     }
     else if (xNode.Attributes["TYPE"].Value == "schedule.NSPDigitalSchedule")
     {
         var tNode2 = new TreeNode(xNode.Attributes["NAME"].Value, ScheduleImageIndex, ScheduleImageIndex);
         inTreeNode.Nodes.Add(tNode2);
         tNode2 = inTreeNode.Nodes[x];
         AddNode(xNode, tNode2);
     }
     else if (xNode.Attributes["TYPE"].Value == "server.point.SV")
     {
         var tNode2 = new TreeNode(xNode.Attributes["NAME"].Value, StringImageIndex, StringImageIndex);
         inTreeNode.Nodes.Add(tNode2);
         tNode2 = inTreeNode.Nodes[x];
         AddNode(xNode, tNode2);
     }
     else if (xNode.Attributes["TYPE"].Value.StartsWith("trend"))
     {
         var tNode2 = new TreeNode(xNode.Attributes["NAME"].Value, TrendImageIndex, TrendImageIndex);
         inTreeNode.Nodes.Add(tNode2);
         tNode2 = inTreeNode.Nodes[x];
             AddNode(xNode, tNode2);
         }
    .
    .
    .and so on

I do not want to add the long list of else if's.

\$\endgroup\$
2
  • \$\begingroup\$ Do you have 1 image type for each type or you have several groups and each group has 1 image? \$\endgroup\$ Sep 5, 2016 at 13:13
  • \$\begingroup\$ Just one image list \$\endgroup\$
    – QANew
    Sep 5, 2016 at 23:30

3 Answers 3

3
\$\begingroup\$

The moment you start copy-pasting code and only changing one small thing, it's time to move that code to a method.

private void CreateAndAddNode(WhateverTypeImagesIndexIs imagesIndex, int x)
{
    var tNode2 = new TreeNode(xNode.Attributes["NAME"].Value, imagesIndex, imagesIndex);
    inTreeNode.Nodes.Add(tNode2);
    tNode2 = inTreeNode.Nodes[x];
    AddNode(xNode, tNode2);
}

I'm assuming AnalogImagesIndex etc. all inherit from some base type; that's the one to use as the method's parameter.


Moreover, all of those ifs can be changed to a switch.

\$\endgroup\$
5
  • \$\begingroup\$ all of those ifs can be changed to a switch. - nope, they cannot, see: .Value.StartsWith("trend") \$\endgroup\$
    – t3chb0t
    Sep 5, 2016 at 8:36
  • \$\begingroup\$ Not until C# 7 where you can have conditions in case \$\endgroup\$
    – t3chb0t
    Sep 5, 2016 at 8:36
  • \$\begingroup\$ @t3chb0t Oops, didn't notice the StartsWith. \$\endgroup\$
    – BCdotWEB
    Sep 5, 2016 at 8:51
  • \$\begingroup\$ I have changed few into swithch switch (xNode.Attributes["TYPE"].Value) { case "server.point.BV": { Then back to default: if where I need to check the starting string \$\endgroup\$
    – QANew
    Sep 5, 2016 at 23:31
  • \$\begingroup\$ I want to be like you when I grow up ^.^ \$\endgroup\$
    – Tolani
    Sep 6, 2016 at 8:35
3
\$\begingroup\$

It doesn't look like you would need the for loop. You can do the same much simpler with a foreach and a little bit of linq:

// assuming they are ints
var AnalogImagesIndex = 0;
var TrendImageIndex = 2;

// simplifies the ifs
var imageIndicies = new Func<string, int?>[]
{
    attr => attr == "server.point.AV" ? AnalogImagesIndex : (int?)null,
    attr => attr.StartsWith("trend") ? TrendImageIndex : (int?)null,
    // ...
};

var imageIndex = imageIndicies
    .Select(x => x(xNode.Attributes["NAME"].Value))
    .First(x => x.HasValue)
    .Value;

To do the rest you can use the helper from BCdotWEB's answer.

Another assumption is that there is no else at the end, otherwise you need to use FirstOrDefault or provide an else lambda.


or with even less repetition the extreme solution:

var getImageIndexOrDefault = new Func<bool, int, int?>(
    (condition, value) => condition ? value : (int?)null);

var imageIndicies = new Func<string, int?>[]
{
    attr => getImageIndexOrDefault(attr == "server.point.AV", AnalogImagesIndex),
    attr => getImageIndexOrDefault(attr.StartsWith("trend"), TrendImageIndex),
};
\$\endgroup\$
3
  • \$\begingroup\$ I have multiple else at the end \$\endgroup\$
    – QANew
    Sep 5, 2016 at 23:34
  • \$\begingroup\$ Wondering if i could skip the node and continue when it comes across a node not satisfying any of the conditions \$\endgroup\$
    – QANew
    Sep 6, 2016 at 0:01
  • \$\begingroup\$ I want to be like you when I grow up ^.^ \$\endgroup\$
    – Tolani
    Sep 6, 2016 at 8:34
0
\$\begingroup\$

On top of @BCdotWEB & @t3chb0t answers you can use the .Any() condition.

For example:

List<string> group1 = new List<string> {"schedule.NSPDigitalSchedule, schedule.Whatever, WhenEver.WhatEver"};

List<string> group2 = ...

 //in foreach loop:
string nodeValue = xNode.Attributes["TYPE"].Value;
if (group1.Any(m=>m==nodeValue)) 
{
   //Call the method for adding image for group1
   continue; //This will go to the next iteration so you don't need nested if's
}

if (group2.Any(m=>nodeValue.StartWith(m)) 
{
    //Call the method for adding image for group2
   continue; 
}

//and so on.

Edit:

Based on the comment you could build your groups for the index you need them like so:

List<string> group1 = new List<string> {"schedule.ImageIndex1, schedule.ImageIndex2, schedule.ImageIndex3"};
//group2...

List<List<string>> groups = new List<List<string>>();
groups.Add(group1, group2...); //or just build in constuctor

foreach (var xNode in xNodes)
{
    string nodeValue = xNode.Attributes["TYPE"].Value;
    //another foreach on all the groups:
    foreach (var group in groups) 
    {
        int currentIndex = group.IndexOf(nodeValue);
        if (currentIndex > -1)
        {
            YourMethodForAddingImg(nodeValue,currentIndex)
            break; //breaks the group foreach and continue to the nodes foreach
        }
    }
}

Only 1 if exist here :)

\$\endgroup\$
6
  • \$\begingroup\$ There is one problem with .Any - the OP needs a different image index for each attribute value and not just a check if it has any of those values. \$\endgroup\$
    – t3chb0t
    Sep 6, 2016 at 8:40
  • \$\begingroup\$ Hmm didn't realize that... return the index of the array maybe? \$\endgroup\$ Sep 6, 2016 at 8:44
  • \$\begingroup\$ Perhaps, but the OP didn't provide enough information to be able to suggest anything about it. We don't know how the image index works or even what data type it is. \$\endgroup\$
    – t3chb0t
    Sep 6, 2016 at 8:45
  • \$\begingroup\$ @QANew Please provide more information about the image index, if possible, you can arrange the List in the same index you need it, and use the IndexOf instead. \$\endgroup\$ Sep 6, 2016 at 8:53
  • \$\begingroup\$ AnalogImagesIndex = 3; //AnalogImagesIndex {get, set}... etc \$\endgroup\$
    – QANew
    Sep 7, 2016 at 23:05

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.