【问题标题】:How to access "statically" instance members of types?如何访问类型的“静态”实例成员?
【发布时间】:2019-07-13 20:46:42
【问题描述】:

我想“静态”访问(即在编译时)给定类型的实例成员(当然是检索它们的静态属性,而不是实际值或类似的东西)。

考虑:

interface IFoo
{
  int X { get; }
}

我想直接访问X 以检索编译时已知的内容,例如:

Console.WriteLine(typeof(IFoo::X).Name);

反射是运行时,我问的是编译时。

【问题讨论】:

  • 您在寻找nameof(Foo.X)?或者换句话说,您想查询成员元数据,例如其类型或名称?您可以为此使用反射。如何做到这一点远远超出了这里的一个问题。
  • 如果你不是只是寻找名字,听起来你想要神话般的infoof运营商:blogs.msdn.microsoft.com/ericlippert/2009/05/21/…
  • @HimBromBeere,谢谢,我知道反射,但为此我需要实例,所以这不是编译时间也不是静态访问。
  • 您不需要实例来检索其元数据,因为该元数据静态绑定到 type,而不是单个 instance。不管你是对的,它是运行时信息。
  • "反射是运行时,我问的是编译时。" 那么答案是"没办法"

标签: c# compile-time


【解决方案1】:

简短回答:您不能在编译时执行此操作。不过,您可以在运行时使用反射来完成。

但是,至少可以使用nameof 获得名称:

nameof(IFoo.Name)

不过,这不会为您提供该成员的编译时类型。

以下功能从未成为语言功能,尽管存在一些要求:

typeof(IFoo.Name)

甚至是 Eric Lipert 提到的 infoof-operator(参见 Jons 的回答)。

【讨论】:

    【解决方案2】:

    不,没有 C# 运算符可以像这样以编译时类型安全的方式引用成员。这是feature that is frequently requested, but really difficult to design well。 C# 6 中引入的nameof 运算符设法绕过了大多数设计问题,同时满足了大多数 用例。

    即使假定的infoof 运算符确实 存在,也不太可能在编译时有办法从中访问特定属性(例如属性的返回类型的名称) .

    如果为了安全而不是为了在编译时实际评估名称,“编译时”部分对您很重要,那么有一些方法可以工作。例如:

    public static class TypeHelpers<TInput>
    {
        public static Type GetReturnType<TOutput>(Func<TInput, TOutput> func) =>
            typeof(TOutput);
    }
    

    然后:

    Type returnType = TypeHelpers<IFoo>.GetReturnType(foo => foo.X);
    Console.WriteLine(returnType.FullName); // System.Int32
    

    这比必须在执行时找到成员要好,但它仍然在执行时请求类型名称。

    【讨论】:

    • 啊,对于生成的Name,我会在运行时使用它,但在编译时会验证整个访问。我在这里不是关于性能,而是有效性。使用反射很容易出错,而使用(希望)静态访问可以在编译时验证一切,所以我的typeof(IFoo::X).Name 是 100% 有效的,而将其转换为反射容易出错,或多或少会出现一个错字编译就好了。太棒了,你在读我的想法,可怕:-)。
    • @astrowalker:是的,我相信 lambda 表达式方法应该避免那个错字问题,尽管它仍然有点难看。
    猜你喜欢
    • 2013-10-28
    • 2012-07-02
    • 2015-01-30
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-19
    相关资源
    最近更新 更多