C#访问泛型类中T类型的静态属性

时间:2011-08-25 07:20:31

标签: c#

我正在尝试完成以下场景:通用TestClassWrapper将能够访问它所构成的类的静态属性(它们都将从TestClass派生)。类似的东西:

public class TestClass
{
    public static int x = 5;
}

public class TestClassWrapper<T> where T : TestClass
{
    public int test()
    {
        return T.x;
    }
}

给出错误:'T' is a 'type parameter', which is not valid in the given context.

有什么建议吗?

7 个答案:

答案 0 :(得分:26)

基本上,你不能没有反思。

一个选项是在您的构造函数中放置一个委托,以便创建实例的人可以指定如何获取它:

var wrapper = new TestClassWrapper<TestClass>(() => TestClass.x);

如果需要,你可以用反射来做到这一点:

public class TestClassWrapper<T> where T : TestClass
{
    private static readonly FieldInfo field = typeof(T).GetField("x");

    public int test()
    {
        return (int) field.GetValue(null);
    }
}

(如有必要,添加适当的绑定标志。)

这不是很好,但至少你只需要查看一次......

答案 1 :(得分:7)

当然你可以写下这个:

public int test() 
{ 
    return TestClass.x; 
} 

即使在一个非常重要的例子中,你也不能覆盖静态字段,因此总是会从已知的基类中调用它。

答案 2 :(得分:1)

为什么不返回TestClass.x

答案 3 :(得分:0)

在这种情况下,您假设T是TestClass的子类。 TestClass的子类不具有静态int x。

答案 4 :(得分:0)

泛型不支持任何与静态成员相关的内容,因此不起作用。我的建议是:不要让它静止。假设该字段真正与特定T相关,您也可以使用反射:

return (int) typeof(T).GetField("x").GetValue(null);

但我不推荐它。

答案 5 :(得分:0)

T是一种类型,而不是参数或变量,因此您无法从任何成员中选择任何值。这是一个示例代码。

public class UrlRecordService
{
    public virtual void SaveSlug<T>(T entity) where T : ISlugSupport
    {
        if (entity == null)
            throw new ArgumentNullException("entity");

        int entityId = entity.Id;
        string entityName = typeof(T).Name;
    }
}


public interface ISlugSupport
{
    int Id { get; set; }
}

答案 6 :(得分:0)

另一种解决方案是简单地使其成为静态,并使用T上的new()约束来实例化对象。然后,您可以使用接口,并且包装器可以从实现该接口的任何类中获取该属性:

public interface XExposer
{
    Int32 X { get; }
}

public class TestClass : XExposer
{
    public Int32 X { get { return 5;} }
}

public class XExposerWrapper<T> where T : XExposer, new()
{
    public Int32 X
    {
        get { return new T().X; }
    }
}

实际上,您可以将其更改为TestClassWrapper上的public static Int32 X,然后将其作为Int32 fetchedX = XExposerWrapper<TestClass>.X;

进行删除

虽然无论代码调用什么,都必须给参数T赋予相同的约束,但此时包装类是非常不必要的,因为调用代码本身也可以只执行new T().X而不用打包器

但是,有一些有趣的继承模型,这种结构很有用。例如,abstract class SuperClass<T> where T : SuperClass<T>, new()可以在其静态函数中实例化并返回类型T,从而有效地允许您创建适应子类的可继承静态函数(然后需要将其定义为class ChildClass : SuperClass<ChildClass>) 。通过在超类上定义protected abstract函数/属性,您可以创建在任何继承对象上应用相同逻辑的函数,但根据这些抽象的实现自定义到该子类。我将它用于数据库类,其中表名和fetch查询由子类实现。由于属性受到保护,因此它们也不会暴露。