list.find question - c#

I am trying to run this code, but a is always null. I made sure that there's a Name, why does it always return null?
public Animal FindAnimal(string Name)
{
Animal a = Animals.Find(
delegate(Animal bk)
{
return bk.AnimalName.ToLower() == Name.ToLower();
}
);
return a;
}

Your code looks fine to me. Here are some small optimizations though:
public Animal FindAnimal(string name)
{
return Animals.Find((a) => String.Equals(a.AnimalName, name, StringComparison.CurrentCultureIgnoreCase));
}
EDIT
Test of code:
void Main()
{
var foundAnimal = FindAnimal("Monkey"); //Not null
}
List<Animal> Animals = new List<Animal>(){ new Animal() { AnimalName = "Monkey" }};
public Animal FindAnimal(string name)
{
return Animals.Find((a) => String.Equals(a.AnimalName, name, StringComparison.CurrentCultureIgnoreCase));
}
public class Animal
{
public string AnimalName { get; set; }
}

Related

Copy list of items to another list

I am trying to copy the list of items from list1 to another list list2. I'm able to do that. However I don't want the changes made in list2 tobe reflected in list1.
class Program
{
static void Main(string[] args)
{
List<MyClass> list1 = new List<MyClass>();
list1.Add(new MyClass(){ID = 1, Name = "name1"});
list1.Add(new MyClass(){ID = 2, Name = "name2"});
list1.Add(new MyClass(){ID = 3, Name = "name3"});
//Copy items from list1 to list2
List<MyClass> list2 = new List<MyClass>(list1);
list1.ForEach(x => Console.WriteLine(x.Name)); //It shows the name as added
//Empty items in list2
list2.ForEach(x => x.Name = string.Empty);
//Print items in list1
list1.ForEach(x => Console.WriteLine(x.Name)); //It shows the name is empty
Console.ReadKey();
}
}
class MyClass
{
private int id;
public int ID
{
get { return id; }
set { id = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
I hope there should be an easy way.
Since this is a reference type you are changing all. You need to create a copy of that instance:
public class MyClass
{
private int id;
public int ID
{
get { return id; }
set { id = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public MyClass Copy()
{
return new MyClass
{
ID = this.ID,
Name = this.Name
};
}
}
Now you can create the second list in this way:
List<MyClass> list2 = new List<MyClass>(list1.Select(x => x.Copy()));
Of course you don't need that method. You could do that also on-the-fly in the LINQ query:
List<MyClass> list2 = new List<MyClass>(list1.Select(x => new MyClass { ID = x.ID, Name = x.Name }));
Another similar approach is a copy-constructor. A copy-constructor is used to initialize an instance by providing another instance of the same type:
public class MyClass
{
private int id;
public MyClass(MyClass instance)
{
this.id = instance.ID;
this.name = instance.Name;
}
public int ID
{
get { return id; }
set { id = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
Now you could fill the list with copies in this way:
List<MyClass> list2 = new List<MyClass>(list1.Select(x => new MyClass(x)));
or with List.ConvertAll:
List<MyClass> list2 = list1.ConvertAll(x => new MyClass(x));
If you want to use this feature in other places too, I guess the best way to do is, to create an extention method for IList like this:
static class Extensions
{
public static IList<T> Clone<T>(this IList<T> sourceList)
where T: ICloneable
{
return sourceList.Select(item => (T)item.Clone()).ToList();
}
}
And to use it, you should change your class and make it ICloneable:
class MyList : ICloneable
{
public MyList(int idParam, string nameParam)
{
ID = idParam;
Name = nameParam;
}
public object Clone()
{
return new MyList(ID, Name);
}
private int id;
public int ID
{
get { return id; }
set { id = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
If your elements are reference types and type implement ICloneable interface you clould do something like this:
list1.ForEach((item) =>
{
list2.Add((ICloneable)item.Clone());
});
If your element type doesn't implement ICloneable, you clould create "copy" constructor and do something like this:
list1.ForEach((item)=>
{
list2.Add(new MyList(item.ID, item.Name));
});

Is it possible to set the property of the condition dynamically?

Normally when I want for example to find the first or default item of a List I use this way:
myList.SingleOrDefault(x=>x.MyPropery01 == "myCondition");
However, I would like to know if it is possible, for example by reflection, if I set the the property MyProperty dynamically, something like:
myList.SingleOrDefault(x=>x.GetType().GetProperty("MyProperty01") == "myCondition");
Because sometimes I need to search for MyProperty01, sometimes for MyProperty02, MyProperty03, etc..
EDIT: in visual studio I get this error:
"Operator '==' can't be applied to operands of type System.reflection.PropertyInfo and string".
Yeah you can do that. You were pretty close, here is a demo you can drop in linqpad. Note that the important part is
Single(l => l.GetType().GetProperty(prop).GetValue(l).ToString() == "Condition")
void Main()
{
var myList = Enumerable.Range(0,10).Select(i => new Xmas(i,"name"+i)).ToList();
string prop = "name";
Console.WriteLine(myList.Single(l => l.GetType().GetProperty(prop).GetValue(l).ToString() == "name6").name);
}
public class Xmas
{
public int id { get; set; }
public string name { get; set; }
public Xmas( int id, string name )
{
this.id = id;
this.name = name;
}
}
Working example:
public class Apple
{
public string Color { get; set; }
}
public List<Apple> ApplesList {get;set;}
public void Process()
{
PropertyInfo pi = typeof(Apple).GetProperty("Color");
ApplesList = ApplesList.Where(r => (string)pi.GetValue(r) == "Red").ToList();
}
You could also write an Extension method, that allow to get the property on every object, returning null when it doesn't exist, or doesn't have a GetMethod. You could keep a Cache if you want
public static class ObjectExtension
{
static IDictionary<KeyValuePair<Type, string>, PropertyInfo> propertyCache = new Dictionary<KeyValuePair<Type, string>, PropertyInfo>();
public static object GetProperty(this object source, string propertyName, bool useCache = true)
{
if (source == null)
{
return null;
}
var sourceType = source.GetType();
KeyValuePair<Type, string> kvp = new KeyValuePair<Type, string>(sourceType, propertyName);
PropertyInfo property = null;
if (!useCache || !propertyCache.ContainsKey(kvp))
{
property = sourceType.GetProperty(propertyName);
if (property == null)
{
return null;
}
var get = property.GetGetMethod();
if (get == null)
{
return null;
}
if (useCache)
{
propertyCache.Add(kvp, property);
}
}
else
{
property = propertyCache[kvp];
}
return property.GetValue(source, null);
}
public static T GetProperty<T>(this object source, string propertyName)
{
object value = GetProperty((object)source, propertyName);
if (value == null)
{
return default(T);
}
return (T)value;
}
}
A small test class could then be:
public class Item
{
public string MyProperty { get; set; }
public string MyProperty3 { get; set; }
public string MyProperty2 { protected get; set; }
public Item()
{
MyProperty = "Test propery";
MyProperty3 = "Test property 3";
MyProperty2 = "Yoohoo";
}
}
With a main class for testing
class Program
{
static void Main(string[] args)
{
Item item = new Item();
for (int x = 0; x < 4; x++)
{
string key = "MyProperty" + (x > 0 ? x.ToString() : "");
string value = item.GetProperty<string>(key);
Console.WriteLine("Getting {0} = {1}", key, value);
}
Console.ReadLine();
}
}
which gives the expectable output of:
Getting MyProperty = Test propery
Getting MyProperty1 =
Getting MyProperty2 =
Getting MyProperty3 = Test property 3

Constructor of type missing - Adding to a generic array with generic method

I'm trying to create an array of generic classes as follows below, however, I'm running into trouble. The first problem is an error "MissingMethodException: Constructor of type Dog not found" when the AddGenericComponent method is called. This method should add whatever class is thrown into it to the components array and also return that component that was just added to be modified in a way similar to as seen "Test()". Does anyone have a suggestion or solution on how to do this?
public void Test()
{
MyClass myClass = new MyClass();
Dog dog = myClass.AddGenericComponent<Dog>();
dog.name = "Fluffy";
Console.Writeline(dog.name);
//testing the accessor
dog = myClass.GetGenericComponent<Dog>();
dog.name = "Fluffy mod";
Console.Writeline(dog.name);
}
public class MyClass
{
//must be an array, not list
GenericComponent<Object>[] components = new GenericComponent<Object>[1];
public T AddGenericComponent<T>()
{
GenericComponent<Object>[] newArray = new GenericComponent<Object>[components.Length + 1];
components.CopyTo(newArray, 0);
components = newArray;
components[components.Length - 1] = new GenericComponent<Object>();
return (T)Activator.CreateInstance(typeof(T), new GenericComponent<Object> { });
}
public T GetGenericComponent<T>()
{
return (T)Array.Find(components, c => c.GetType() == typeof(T)).component;
}
}
public class GenericComponent<T> where T: new()
{
public T component;
public GenericComponent()
{
component = new T();
}
}
public class Dog
{
public string name = "";
public Dog(){}
public Dog(string name)
{
this.name = name;
}
}
Edit:
I think I've solved it.
public T AddGenericComponent<T>()
{
GenericComponent<Object>[] newArray = new GenericComponent<Object>[components.Length + 1];
components.CopyTo(newArray, 0);
components = newArray;
GenericComponent<Object> newComponent = new GenericComponent<Object>();//;(T)Activator.CreateInstance(typeof(T));
newComponent.component = (T)Activator.CreateInstance(typeof(T));
components[components.Length - 1] = newComponent;
return (T)Activator.CreateInstance(typeof(T));
}
I don't really understand what you tried to do here but:
public static object CreateInstance(Type type, params object[] args);
The args are the ctor params.
Activator.CreateInstance(typeof(Dog)); -> this will invoke the public Dog(){} ctor.
Activator.CreateInstance(typeof(Dog),"myString"); -> this will invoke the public Dog(string name){} ctor.
Activator.CreateInstance(typeof(T), new GenericComponent<Object> { }); -> this will invoke the public Dog(GenericComponent<Object> param){} ctor that doesnt exist and therefore you get the exception.
Edit:
I tried to understand why you did what you did but couldn't. Anyway it looks like you wanted something like this:
public void Test()
{
MyClass myClass = new MyClass();
Dog dog = myClass.AddGenericComponent<Dog>();
dog.name = "Fluffy";
MessageBox.Show(dog.name);
//testing the accessor - ADD a NULL CHECK!!!
dog = myClass.GetGenericComponent<Dog>();
dog.name = "Fluffy mod";
MessageBox.Show(dog.name);
}
public class MyClass
{
List<Object> objects = new List<Object>();
public T AddGenericComponent<T>() where T : class, new()
{
T obj = GetGenericComponent<T>();
if (obj == null)
{
obj = new T();
objects.Add(obj);
}
return obj;
}
public T GetGenericComponent<T>() where T : class, new()
{
var relevantObj = objects.FirstOrDefault(o => o.GetType() == typeof(T));
if (relevantObj != null)
{
return relevantObj as T;
}
return null;
}
}
public class Dog
{
public string name = "";
public Dog() { }
public Dog(string name)
{
this.name = name;
}
}
I got it working with the following:
class Test
{
public void TestStart()
{
MyClass myClass = new MyClass();
Dog dog = myClass.AddGenericComponent<Dog>();
dog.name = "Fluffy";
Console.Writeline(dog.name);
//testing the accessor
dog = myClass.GetGenericComponent<Dog>();
dog.name = "Fluffy mod";
Console.Writeline(dog.name);
}
}
[Serializable]
public class GameObject
{
List<GenericComponent<Object>> componentList = new List<GenericComponent<Object>>();
//returns first found in list.
public T GetComponent<T>()
{
return (T)componentList.Find(c => c.component.GetType() == typeof(T)).component;
}
//add a component to component list.
public T AddComponent<T>()
{
GenericComponent<Object> newComponent = new GenericComponent<Object>();
newComponent.component = (T)Activator.CreateInstance(typeof(T));
componentList.Add(newComponent);
return (T)newComponent.component;
}
//returns all components of type T
public List<T> GetComponents<T>()
{
List<T> r = new List<T>();
for (int i = 0; i < componentList.Count; i++)
{
if (componentList[i].component.GetType() == typeof(T))
{
r.Add((T)componentList[i].component);
}
}
return r;
}
}
[Serializable]
public class GenericComponent<T> where T : new()
{
public T component;
public GenericComponent()
{
component = new T();
}
}
[Serializable]
public class Dog
{
public string name = "";
public Dog() { }
public Dog(string name)
{
this.name = name;
}
}

Giving an Enum static properties

I had originally written my solution using an enum:
enum Speicies {
monosiga,
leidyi,
queelslandica,
hydra
};
But then I wanted to add constant properties to each of the enum options. i.e.
Speicies myOrganism = monosiga;
Console.writeLine(myOrganism.database);
Console.writeLine(myOrganism.class);
//Output:
// c:\monosigadb.fasta
// Choanoflagellatea
This would imply that I should use a static class where I could use literals for the database and class variables for each species.
However, I wanted to retain the ability to have a Species object.
What would be the approach to this type of "advance enum"?
here's what I was getting at:
class Program
{
static void Main(string[] args)
{
List<ISpecies> species = new List<ISpecies>();
species.Add(new Cat());
species.Add(new Dog());
foreach (var specie in species)
{
Console.WriteLine(specie.ClassProp);
Console.WriteLine(specie.DatabaseProp);
}
Console.Read();
}
public interface ISpecies
{
string ClassProp { get; }
string DatabaseProp { get; }
}
public class Cat : ISpecies
{
public string ClassProp { get { return "Cat Class Property"; } }
public string DatabaseProp { get { return "Cat Database Propery"; } }
}
public class Dog : ISpecies
{
public string ClassProp { get { return "Dog Class Property"; } }
public string DatabaseProp { get { return "Dog Database Propery"; } }
}
}

Verify that correct method was passed in a function call

My test class takes 2 objects in its constructor, a data loader and a class that consumes the data returned from the data loader.
The data loader interface has 2 functions, LoadCompanies() and LoadEmployees(), both of which take an int parameter and return an IEnumerable.
How can I verify that the method under test passes LoadCompanies() and NOT LoadEmployees() into the data consumer class?
Here is my code:
[TestFixture]
public class TestingFunctionalParameters_UT
{
[Test]
public void Correct_Loader_Method_is_Used()
{
const int userId = 1;
var companies = new[] { "c1", "c2" };
var dataLoader = MockRepository.GenerateMock<ITestDataLoader>();
var dataConsumer = MockRepository.GenerateMock<IDataConsumerClass>();
var testObject = new TestClass(dataLoader, dataConsumer);
dataConsumer.Expect(fc => fc.LoadIt(Arg<Func<IEnumerable<string>>>.Is.TypeOf)).Return(true);
//TODO: validate that correct dataloader function was called...
//dataLoader.Expect(dl => dl.LoadCompanies(userId)).Return(companies);
var result = testObject.Run(userId);
Assert.That(result, Is.True);
dataLoader.VerifyAllExpectations();
dataConsumer.VerifyAllExpectations();
}
}
public class TestClass
{
private readonly ITestDataLoader dataLoader;
private readonly IDataConsumerClass funcClass;
public TestClass(ITestDataLoader dataLoader, IDataConsumerClass funcClass)
{
this.dataLoader = dataLoader;
this.funcClass = funcClass;
}
public bool Run(int userId)
{
Func<IEnumerable<string>> loadFn = () => dataLoader.LoadCompanies(userId);
return funcClass.LoadIt(loadFn);
}
}
public interface ITestDataLoader
{
IEnumerable<string> LoadCompanies(int userId);
IEnumerable<string> LoadEmployees(int userId);
}
public interface IDataConsumerClass
{
bool LoadIt(Func<IEnumerable<string>> load);
}
You could create companies and employees classes
class Company
{
public Company(string name)
{
Name = name;
}
public string Name { get; private set; }
public override string ToString()
{
return Name;
}
}
Do the same for employees and then define your interface like this
public interface ITestDataLoader
{
IEnumerable<Company> LoadCompanies(int userId);
IEnumerable<Employee> LoadEmployees(int userId);
}
Now companies and employees cannot be confused any more.
EDIT:
If you have a lot of cases like that, you could create a common base class
class NamedItem
{
public NamedItem(string name)
{
Name = name;
}
public string Name { get; private set; }
public override string ToString()
{
return Name;
}
}
class Company : NamedItem
{
public Company(string name)
: base(name)
{
}
}
class Employee : NamedItem
{
public Employee (string name)
: base(name)
{
}
}
(Edit: I am assuming that your example is a simplified one, and your actual implementation is an attempt to test a delegate injection pattern)
Maybe you could write your test like this? (Edited to actually compile)
[Test]
public void Correct_Loader_Method_is_Used()
{
const int userId = 1;
var companies = new[] { "c1", "c2" };
var dataLoader = MockRepository.GenerateMock<ITestDataLoader>();
var dataConsumer = MockRepository.GenerateMock<IDataConsumerClass>();
var testObject = new TestClass(dataLoader, dataConsumer);
dataConsumer.Expect(fc => fc.LoadIt(Arg<Func<IEnumerable<string>>>.Matches(x => x().Any()))).Return(true);
//validate that correct dataloader function was called...
dataLoader.Expect(dl => dl.LoadCompanies(userId)).Return(companies);
// Fails if you uncomment this line
//dataLoader.Expect(dl => dl.LoadEmployees(userId)).Return(companies);
var result = testObject.Run(userId);
Assert.That(result, Is.True);
dataLoader.VerifyAllExpectations();
dataConsumer.VerifyAllExpectations();
}
Basically the Matches() constraint will try execute the method, and if it tries to call LoadEmployees(), RhinoMocks will complain because it doesn't have a defined mock.
Update: Handling Action<T> delegates
This might be a little less robust, but for Action<T>s:
public interface IDataConsumerClass
{
bool LoadIt(Func<IEnumerable<string>> load);
bool ExecuteIt<T>(Action<T> execute);
}
//...
dataConsumer.Expect(fc => fc.ExecuteIt(Arg<Action<int>>.Matches(x => ActionWrapper(x, userId)))).Return(true);
//...
private bool ActionWrapper<T>(Action<T> action, T arg)
{
action(arg);
return true;
}

Categories