Reputation: 15
So I have a CreditCard class that has some properties, one of which is for the card number as a String (public string Number { get; set; }
). I'm storing the CreditCard objects in a CreditCardList class which has the variable List (private List<CreditCard> cclist = new List<CreditCard>();
). I want to be able to retrieve a CreditCard by its card number by sorting the List first, then using the BinarySearch method on the List. I also want to do this by passing a String indexer of the number to search for into the BinarySearch method, along with a comparer if I need one.
This is what I have so far for the method to get the CreditCard matching the number, but Visual Studio 2013 gives me an error on the line: int index = cclist.BinarySearch(cclist[input], new CreditCardComparer());
"the best overloaded method match for 'System.Collections.Generic.List.this[int]' has some invalid arguments." I assume it's because I'm using the String indexer wrong or something.
public List<CreditCard> GetCardByNumber (string input)
{
List<CreditCard> tempList = new List<CreditCard>();
// save the current unsorted list to a temporary list to revert back to after sorting
List<CreditCard> originalList = new List<CreditCard>(cclist.Capacity);
for (int i = 0; i < cclist.Capacity; i++)
{
originalList[i] = cclist[i];
}
// begin sorting for binary search of card number
cclist.Sort();
int index = cclist.BinarySearch(cclist[input], new CreditCardComparer());
if (index < 0)
{
tempList.Add(cclist[input]);
}
// revert back to the original unsorted list
for (int i = 0; i < originalList.Capacity; i++)
{
cclist[i] = originalList[i];
}
// return the found credit card matching the specified number
return tempList;
}// end GetCardByNumber (string input)
Here are my int and string indexers:
public CreditCard this[int i]
{
get
{
if (i < 0 || i >= cclist.Count)
{
throw new ArgumentOutOfRangeException("index " + i + " does not exist");
}
return cclist[i];
}
set
{
if (i < 0 || i >= cclist.Count)
{
throw new ArgumentOutOfRangeException("index " + i + " does not exist");
}
cclist[i] = value;
saveNeeded = true;
}
}// end CreditCard this[int i]
public CreditCard this[string input]
{
get
{
foreach (CreditCard cc in cclist)
{
if (cc.Number == input)
{
return cc;
}
}
return null;
}
}// end CreditCard this[string number]
And here is my comparer class:
public class CreditCardComparer : IComparer<CreditCard>
{
public override int Compare(CreditCard x, CreditCard y)
{
return x.Number.CompareTo(y.Number);
}
}// end CreditCardComparer : IComparer<CreditCard>
And lastly, here are the necessities for my list sorting and what not...
class CreditCard : IEquatable<CreditCard>, IComparable<CreditCard>
{
public bool Equals (CreditCard other)
{
if (this.Number == other.Number)
{
return true;
}
else
{
return false;
}
}// end Equals(CreditCard other)
public int CompareTo(CreditCard other)
{
return Number.CompareTo(other.Number);
}// end CompareTo(CreditCard other)
}
Is it truly possible to do what I'm attempting, i.e. sending a string indexer that returns a CreditCard object based on a string into a BinarySearch method of List?
Also, I can provide any more code if necessary, but I felt like this was a little much to begin with.
Upvotes: 0
Views: 465
Reputation: 2011
There are a couple things amiss in your GetCardByNumber
method. First is the method returns an entire list instead of a single CreditCard, which goes against the method name. Second, the binary search is not even needed since you do the searching in the string indexer first:
public CreditCard this[string input]
{
get
{
foreach (CreditCard cc in cclist)
{
if (cc.Number == input)
{
return cc;
}
}
return null;
}
}
By this point, you've already found the CreditCard with the information you need, so why search for it again in a BinarySearch? Thirdly, as was covered in landoncz's answer, you can't use a string as an index for a List<T>
. What you probably intended to use was the CreditCardList
instead of the List<CreditCard>
CreditCardList creditCardList = new CreditCardList();
creditCardList["1234"]; //correct
List<CreditCard> cclist = new List<CreditCard>();
cclist["1234"]; //incorrect. This is where your error is coming from.
If you're trying to access the indexer property inside of the class that implements it (which I'm assuming you are trying to do in your GetCardByNumber method), just use this[index]
:
public class CreditCardList
{
public CreditCard this[string s] { /*Implementation*/ }
public CreditCard GetCard(string s)
{
return this[s]; // right here!
}
}
Now... according to your comment, "Retrieve the CreditCard with a specified number if it exists using the BinarySearch method in List<T> in the implementation of a String indexer.
", it seems to me that the assignment wants you doing something along these lines. (a thing to note is that I'm not sure of your entire implementation of the CreditCard class, so please excuse the naive instantiation in the following code)
public class CreditCardList
{
private List<CreditCard> cclist = new List<CreditCard>();
public CreditCardList()
{
//For the sake of an example, let's magically populate the list.
MagicallyPopulateAList(cclist);
}
public CreditCard this[string s] /* In the implementation of a String indexer... */
{
get
{
CreditCard ccToSearchFor = new CreditCard() { Number = value };
cclist.Sort();
/* ...use the BinarySearch method... */
int index = cclist.BinarySearch(ccToSearchFor);
if (index >= 0)
return cclist[index]; /* ...to retrieve a CreditCard. */
else
throw new ArgumentException("Credit Card Number not found.");
}
}
}
Upvotes: 0
Reputation: 2017
A System.Collections.Generic.List
uses an int
as the indexer property, it does not let you use a string.
If you want to use a string as your indexer (primary key), you should probably use a Dictionary<string,CreditCard>
instead.
Upvotes: 1