从泛型对象中获取值(可能不存在)

本文关键字:不存在 泛型 对象 获取 | 更新日期: 2023-09-27 18:00:10

我需要一个列表,它可以查询特定属性的项,然后在该属性具有正确值的情况下返回该项。我想到了以下内容:

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

上面给出了一个编译错误,因为类型T不一定具有我正在检查的属性。这是有道理的,但我该怎么做才能得到这种行为。请注意,我不能使用词典的原因超出了这个问题的范围,尽管词典确实是我试图重新创建的重要内容。

从泛型对象中获取值(可能不存在)

在函数定义后面设置一个约束

public class MyList<T> where T : YourObjectThatHasNameProperty

您可以像这样使用反射:

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);
}

编辑:如果函数返回null,则可以假设所提供的Object上不存在该属性。

您可以使用反射来查看T是否具有以下属性:

Type type = item.GetType();
bool hasproperty = type.GetProperties().Where(p => p.Name.Equals("name")).Any();

您需要将T约束为具有以下属性的类型:

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

然后,例如,

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");

使用通用约束。

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