Click here to Skip to main content
15,886,199 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
Hi all, i have query and i would be really thankful if you could help me.
I have list<customer> with a property name SNO.

I have written a code
Public Void delete(List<Customer> dataList,String MatchedSno)
{
if(!String.IsNullOrEmpty(MatchedSno))
dataList.RemoveAll(a=>a.SNO==Convert.ToInt32(MatchedSno));
else
dataList.RemoveRange(1,dataList.Count-1);

}


But i want to create a generic method with List of Type <t> and now want to achieve the Same i.e.
Public Void delete<T>(List<T> dataList,String MatchedSno)
{
if(!String.IsNullOrEmpty(MatchedSno))
dataList.RemoveAll(a=>a.SNO==Convert.ToInt32(MatchedSno));
else
dataList.RemoveRange(1,dataList.Count-1);

}


Please give me an optimized solution for this.
Thank You
Posted
Comments
Tomas Takac 13-Nov-14 15:10pm    
Do you expect all the objects will have a SNO property? Or the key will be different for each class?
PIEBALDconsult 13-Nov-14 15:17pm    
Unrelated:
Convert.ToInt32(MatchedSno));
If you don't want a string, don't pass in a string. Perform the conversion/parsing before calling the method.

Other than that, you may need a where clause to say that type T must be a type with a SNO.
Member 10582972 13-Nov-14 15:27pm    
I have only 1 class Customer and SNO is its property,so all object will have SNO property
Tomas Takac 13-Nov-14 15:37pm    
Then what do you need a generic method for?
BillWoodruff 14-Nov-14 1:51am    
That's a very good question, Tomas, but, let's see the OP wanting to know how to do it generically is a sign they want to learn (yes, I try to be an optimist) :)

Generics only makes sense if you really have different type for the list element, and all those types have a common (inherited) member to be used to to filter out the objects to be removed (or provide any common functionality at all). Then you would use generic type constraints to identify this common type. As you did not specify it, the question does not make sense. However, the idea to use generics may make sense, if you do what I mentioned above.

Besides, using string parameter in your delete method is not just silly, it's a crime (against yourself). You always compare integer property/field, so it should be integer parameter. And, if you parse a string to integer (or anything), uses int.Parse, not Convert. Finally, your code samples could not compile, because C# is case-sensitive. Why posting not real code?

Let me illustrate the idea on a simple example, which may not match your case:
C#
interface ISno
{
    int Sno { get; set; }
}
class Customer : ISno
{
    public int Sno { get; set; }
}

static class Test
{
    internal static void SelectiveDeleteSno<T>(List<T> list, int snoToMatch)
        where T : ISno // this constraint give access to ISno.Sno
    {
        list.RemoveAll(a => a.Sno == snoToMatch); // now you can do it
    }
}

So, if you have anything to specify the constraint, you can do it. If you did not have filtering and had to do something with some collection without using any knowledge on the elements, it could be any non-specified element type, so generic constraint would not be needed.

—SA
 
Share this answer
 
Comments
BillWoodruff 13-Nov-14 16:04pm    
+5 Hi Sergey, I did not see your answer until after I had posted my response ... there's often a delay of up to thirty minutes before I get updates here ... but I am delighted that I was, temporarily, on your wavelength :)
Sergey Alexandrovich Kryukov 13-Nov-14 16:22pm    
Thank you, Bill.
—SA
The way I can see to accomplish what you seem to want is:
Pass a delegate to the method that pulls out the value:
C#
public void delete<T>(List<T> dataList, Func<T, int> getSno, string MatchedSno)
{
  if(!string.IsNullOrEmpty(MatchedSno))
  {
    int match = Convert.ToInt32(MatchedSno);
    dataList.RemoveAll(a => getSno(a) == match);
  }
  else
    dataList.RemoveRange(1, dataList.Count-1);
}

Note that I convert MatchedSno to an integer only once, not every time in the lambda. Using int.TryParse() would be better than Convert.ToInt32(), you can handle errors more cleanly.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 13-Nov-14 16:24pm    
This is a different solution, more loosely coupled then mine, so this is a very good alternative.
I voted 4 (not 5) only because you still followed bad OP's idea to convert string to integer and to have a string parameters at all. Another pointless thing is to RemoveRange. This should not even be done in this method.
—SA
The interesting challenge here is how to make this a generic method, but ensure that every List passed into it for manipulation implements a Property named 'Sno.

The way that is done is with a method constraint based on an Interface:
C#
public interface ISno
{
    int Sno { set; get; }
}

public void delete<t>(List<t> dataList, string MatchedSno) where T : ISno
{
    if (string.IsNullOrEmpty(MatchedSno))
    {
        dataList.RemoveRange(1,dataList.Count-1);
        return;
    }

    int intSNO = Convert.ToInt32(MatchedSno);

    dataList.RemoveAll(itm => itm.Sno == intSNO);            
}</t></t>
Test: Define two classes, one that implements ISno and one that doesn't:
C#
        public class HasSno : ISno
{
    public int Sno { set; get; }

    public HasSno(int sno)
    {
        Sno = sno;
    }
}

public class NoSno
{
    public int Sno { set; get; }

    public NoSno(int sno)
    {
        Sno = sno;
    }
}
Now we can test:
C#
private void SomeButton_Click(object sender, EventArgs e)
{
    var listHasSno = new List<hassno>();
    var listNoSno = new List<nosno>();

    for (int i = 0; i < 30; i++)
    {
        int m = i % 5; // value in series 0~4

        listHasSno.Add(new HasSno(m));

        listNoSno.Add(new NoSno(m));
    }

    delete(listHasSno, "3");

    // confirm all 'HasSno in list with 'Sno == 3 are deleted
    foreach (var sno in listHasSno) Console.WriteLine(sno.Sno);

    // this will fail:
    // delete(listNoSno, "2");
    // ftype 'noSno cannot be used as type parameter 'T' 
    // in the generic type or method delete<t>(System.Collections.Generic.List<t>, string)'.
    // There is no implicit reference conversion from 'noSno' to 'ISno'
}</t></t></nosno></hassno>
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 13-Nov-14 16:27pm    
I voted 4 (not 5) only because you still followed bad OP's idea to convert string to integer and to have a string parameters at all. Another pointless thing is to RemoveRange. This would be just Clear... [EDIT] is a method removing all elements except the first one [END EDIT], and it should not even be done in this method.
Matt did the same in Solution 2, but he did it in much more loosely coupled way than our solutions.
—SA
BillWoodruff 13-Nov-14 16:32pm    
I'm fine with your vote, always, Sergey. The behavior the OP specified if the string parameter was null or empty was to remove the last item in the list, not to clear the list. It doesn't bother me the OP used a string parameter: I assume in this case they wanted the "extra" behavior of deleting one item tacked-on to the multi-delete facility.
Sergey Alexandrovich Kryukov 13-Nov-14 16:43pm    
Sorry, no, but I also wasn't right. This call removes all elements except first one. Also a bad thing. This should not even be done in this method. A separate non-generic method should be better. Coding a subliminal role of null to indicate that the desire of the caller is to remove all items except first one is just cryptic. The use of null string should be natural, so the most likely expectation of the user would be implemented.

For example, it would natural enough to try to return a null error string in a "no errors" situation, but who, in sober mind, would come to an idea to indicate that all elements except one should be removed? Having one extra method with the name explicitly expressing this idea would be more code, but at least nothing cryptic.

—SA
BillWoodruff 14-Nov-14 1:49am    
Ah, yes, you're right: my mind dyslexed the arguments and saw "remove the last one" :) While I am willing to take the OP's request at "face value," and respond to it with what they specify, that does not mean that I would choose to write code the same way. The goal of the OP here to move to a Generic function also suggests, to me, using a string parameter is okay.
Sergey Alexandrovich Kryukov 14-Nov-14 2:26am    
The worst thing here, as I said many times, a present-day trend to work with strings representing data instead of data. Passing a string where an integer is expected is really, really bad. Performance is bad, and this is not the worst thing...
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900