public static int IndexOf(Product[] products, Predicate<Product> predicate)
{
if (products == null)
{
throw new ArgumentNullException();
}
for (int i = 0; i <= products.Length - 1; i++)
{
if (predicate == null)
{
throw new ArgumentNullException();
}
Product product = products[i];
if (predicate(product))
{
return i;
}
}
return -1;
}
- Searches for the index of a product in an products based on a predicate
products Products used for searching
predicate Product predicate
If match found then returns index of product in products
otherwise -1
I am asked to make changes only in the IndexOf(Product[] products, Predict predict) method without touching the Product model.
[Test]
public void IndexOf_Products_ReturnsTwo()
{
var products = new Product[]
{
new Product("Product 1", 10.0d),
new Product("Product 2", 20.0d),
new Product("Product 3", 30.0d),
};
var productToFind = new Product("Product 3", 30.0d);
int index = Utilities.IndexOf(products, product => product.Equals(productToFind));
Assert.That(index, Is.EqualTo(2));
}
- Expected: 2 But was:-1
public class Product
{
public Product(string name, double price)
{
Name = name;
Price = price;
}
public string Name { get; set; }
public double Price { get; set; }
}
>Solution :
Well IndexOf is a correct implementation, which can be make to more general:
public static int IndexOf<T>(IEnumerable<T> source, Predicate<T> predicate)
{
if (products is null)
{
throw new ArgumentNullException(nameof(source));
}
if (predicate == null)
{
throw new ArgumentNullException(nameof(predicate));
}
int index = 0;
foreach (T item in source) {
if (predicate(item))
return index;
index += 1;
}
return -1;
}
The actual problem seems to be with Product class which doesn’t override Equals and GetHashCode methods.
Without Equals and GetHashCode .net compare references (which are different), not values.
To compare by values you should explain .net how to do it, something like this:
// Let Product be equatable with Product - IEquatable<Product>
public class Product : IEquatable<Product> {
...
// Let .net know how to compare for equality:
//TODO: put the right names for Name and Price
public bool Equals(Product other) => other != null &&
other.Name == Name &&
other.Price == Price;
public override bool Equals(object o) => o is Product other && Equals(other);
public override int GetHashCode() => HashCode.Combine(Name, Price);
}