【问题标题】:c# class reference as opposed to instance referencec# 类引用而不是实例引用
【发布时间】:2012-02-20 17:09:21
【问题描述】:

我可以在 C# 中本地引用一个类,而不是一个类的实例吗?以下代码无法编译,但例如:

void someFunc()
{
    var a = System.Math;
    var b = a.Abs(4);
}

编辑:在实际程序中,它不是 System.Math 类,我想构造类并返回构造值。最初我不认为我想使用该类的上下文是相关的,而且可能不应该是。

Anastasiosyal 有一个有趣的想法,即使用本地代表来实现。

【问题讨论】:

  • 是的,你可以做到。但是你为什么要这样做呢?
  • 你想解决什么问题,这会有所帮助?
  • 具有本地范围的本地别名,用于在复杂系统中的特定上下文范围内的长层次类名。这可能是使用它的最微不足道的原因。
  • 类名长是因为它们属于命名空间层次结构,还是您有深度嵌套的类?
  • VB.NET 通过 Imports 语句支持类型名称别名。 C# 没有这个特性。

标签: c# class variables reference instance


【解决方案1】:

你可以引用一个类:

Type math = typeof(System.Math);

但是您不能使用常规的点语法对其调用静态方法:

// Wont compile:
math.Abs(5);

如果您只想缩短(恕我直言混淆)您的代码,您可以reference classes with aliases via a using directive

// Untested, but should work
namespace MyUnreadableCode {
    using m = System.Math;
    class Foo {
        public static Int32 Absolut(Int32 a) {
            return m.Abs(a);
        }
    }
}

【讨论】:

  • 在 C# 4 中,可以使用新的 dynamic 关键字在 Type 对象上调用静态方法。它需要一些额外的管道(而且它并不漂亮),但它可以工作。 (Source)
  • 您所说的 Type 方法不允许调用静态方法,并且看起来它调用任何东西都没有太多混淆,并且命名空间方法不允许使用 using 语句非常本地化,尽管在这种情况下它可能是最好的。我通常不喜欢“using”,例如,我不喜欢在顶部使用长长的“using”列表来使命名空间层次结构(如以“System”开头的命名空间层次结构看起来很扁平。
  • 我实际上是在一个环境中运行的,这可能是由于 XNA 的“动态”无法正常工作。尽管对于 C# 编码人员来说这似乎是有争议的,但我是它的忠实拥护者,并且不认为它会损害安全性。
  • 我对使用 using 指令扁平化命名空间没有任何问题(using 的“经典”使用)。我只是认为别名特别混乱,因为它极大地干扰了我阅读代码的能力。
【解决方案2】:

您不能为变量分配静态类的值。问题是为什么你要这样做,可能还有其他方法可以解决你的问题

例如您可以使用委托来分配您要执行的操作:

Func<int,int> operation = Math.Abs; 
// then you could use it like so: 
int processedValue = operation(-1);

【讨论】:

  • 这是一个有趣的想法,可以工作,并且可能是迄今为止最好的解决方案,虽然在我的例子中操作是构造和返回,数学课只是一个例子,更重要的是长理想情况下,我不想以重复的描述结束参数列表。我看不出有什么替代方法可以实现同样的事情,这使我原来的方法出错了,它在 C# 中不可用。
  • 如果您正在寻找创建模式,您将受益于工厂模式或Inversion of Control 描述的Here
  • 这是最接近我需要和描述的,标记为正确,抱歉耽搁了。
【解决方案3】:

在 c# 中,它们被称为类型。你可以像这样分配它们:

Type a = typeof(SomeClass);

但是,您必须实例化它才能使用它。我相信您想要的是像 java 中那样的静态导入,但不幸的是,它们在 c# 中不存在。

简短回答:不像你上面所说的那样。

【讨论】:

    【解决方案4】:

    在 C# 6.0 中他们引入了static import feature,可以解决问题。

    using static System.Math;
    
    class MyProgram
    {
        static void Main(string[] args)
        {
            var b = Abs(4); // No need to specify the name of Math class
        }
    }
    

    【讨论】:

      【解决方案5】:

      据我了解,您需要使用短名称来引用该类?试试这个(在文件顶部,在 using 语句部分内):

      using m = System.Math;
      

      稍后在您的代码中:

      m.Abs(...)
      

      有道理吗?

      【讨论】:

      • 查看我对 Chris Shain 的回答的评论。这并不理想,但可能已经足够了。
      【解决方案6】:

      没有。不可能将 Type 视为实例方法绑定到原始类型上的静态方法的值。为此,您需要构造一个新类型,将其方法调用转发给原始类型。

      class MyMath { 
        public int Abs(int i) {
          return Math.Abs(i);
        }
      }
      
      var x = new MyMath();
      

      【讨论】:

      • 可能你的例子可以通过继承来改进,MyMath 继承自 System.Maths
      • @alan2here 为什么会有所改善?
      • 因为 MyMath 将与 System.Math 相同,而不是仅具有一个转发功能。
      • @alan2here 虽然这不是真的。 System.Math 唯一有趣的是它的静态方法和 sattic 方法不参与继承。另外System.Math 是一个静态类,因此不能被继承。
      猜你喜欢
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 2017-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-01
      • 1970-01-01
      相关资源
      最近更新 更多