Getting value (that may not exist) from within generic object
I need a list which can have its items queried for a particular property, and then returns the item if that property has the correct value. I came up with the following:
public class MyList<T>
{
public T[] items;
public Get( string name )
{
foreach( T item in items )
{
if( item.name == name )
return item;
}
return null; // if not found
}
}
The above gives a compile error because type T doesn't neces开发者_开发技巧sarily have the property that i'm checking. That makes sense, but what do I have to do to get this behaviour. Please note that I cannot use a Dictionary for reasons outside the scope of this question, although it is true that a Dictionary is essential what i'm trying to re-create.
Put a constraint behind your function definition
public class MyList<T> where T : YourObjectThatHasNameProperty
You could use Reflection like this:
public static Object TryGetPropertyValue(Object fromThis, String propertyName, Boolean isStatic)
{
// Get Type
Type baseType = fromThis.GetType();
// Get additional binding flags
BindingFlags addFlag = BindingFlags.Instance;
if(isStatic)
addFlag = BindingFlags.Static;
// Get PropertyInfo
PropertyInfo info = baseType.GetProperty(propertyName, BindingFlags.Public | addFlag);
// Check if we found the Property and if we can read it
if(info == null || !info.CanRead)
return null;
// Return the value
return info.GetValue(fromThis, null);
}
Edit: If the function return null
, you can assume that the property does not exist on the provided Object.
You could use reflection to see if T
has that property:
Type type = item.GetType();
bool hasproperty = type.GetProperties().Where(p => p.Name.Equals("name")).Any();
You need to constrain T
to be of a type that has such a property:
interface INamed {
string Name { get; }
}
public class MyList<T> where T : INamed
public T[] items;
public T Get( string name ) {
foreach( T item in items ) {
if( item.Name == name )
return item;
}
return null; // if not found
}
}
Then, for instance,
class Foo : INamed {
private readonly string name;
private readonly int foo;
public string Name { get { return this.name; } }
public Foo(string name, int foo) {
this.name = name;
this.foo = foo;
}
}
MyList<Foo> list = // some instance of MyList<Foo>
Foo alice = list.Get("Alice");
Use a generic constraint.
public interface IHasName
{
string name;
}
public class MyList<T> where T : IHasName
{
public T[] items;
public Get( string name )
{
foreach( T item in items )
{
if( item.name == name )
return item;
}
return null; // if not found
}
}
精彩评论