开发者

Getting value (that may not exist) from within generic object

开发者 https://www.devze.com 2023-03-15 09:09 出处:网络
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:

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
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消