【问题标题】:Returning 'this' in a static method在静态方法中返回“this”
【发布时间】:2012-04-26 23:45:37
【问题描述】:

我想创建一个具有流畅界面的静态类,但出现错误:

'this' 在静态属性、方法中无效...

这是我的代码:

public static MyClass
{
    private static StringBuilder builder;
    private static StringBuilder RouteBuilder
    {
        get
        {
            if (builder == null)
                builder = new StringBuilder();

            return builder;
        }
    }

    public static MyClass Root()
    {
      RouteBuilder.Append("/");
      return this;
    }

    public static MyClass And()
    {
      RouteBuilder.Append("and");
      return this;
    }

    public static MyClass Something()
    {
       RouteBuilder.Append("something");
       return this;
    }
}

这使我能够做到MyClass.Root().And().Something();

有没有办法做到这一点或解决方法?

【问题讨论】:

  • 您希望 this 在您的静态方法中使用什么?
  • 我最近写了一个blog post 来介绍流畅的构建器界面,这可能会有所帮助

标签: c# .net this static-classes


【解决方案1】:

你不能在静态方法中使用'this'关键字,因为'this'返回类的当前实例。但是静态方法不属于任何实例(相反,它们属于类本身),因此无法返回它。

为什么你的类和方法需要是静态的?删除所有静态关键字将使其工作。如果你,请改用Singleton pattern

【讨论】:

    【解决方案2】:

    return RouteBuilder 会成功的!

    编辑:错了,对不起

    对于这些情况,你也可以只做一个扩展类

     public static class StringBuilderExtensions {
    
        public static StringBuilder Root(this StringBuilder builder) {
          Asserts.IsNotNull(builder);
         builder.Append("/");
         return builder;
        }
    
       public static StringBuilder And(this StringBuilder builder) {
         Asserts.IsNotNull(builder);
         builder.Append("and");
         return builder;
       }
       //...etc
     }
    

    并像使用它

    var builder = new StringBuilder();
    builder.Root().Append()
    

    【讨论】:

    • 您的更改仍然很糟糕,因为返回 StringBuilder 并不能传达您正在做的事情的意图。在StringBuilder 上调用And 的方法毫无意义。
    • 好吧,我同意你的看法。这只是一种扩展方式的示例。一个名为 MyClass 的类也不那么明确;)但我认为你的意思是这种扩展在“封闭”类中更好,而不是纯 StringBuilder 扩展,我也同意。
    【解决方案3】:

    我很惊讶该语言甚至允许这样做 - 您定义的方法清楚地返回一个实例,但在同一个类定义中,您声明您永远不能创建它的实例。

    您仍然可以在普通类上定义静态方法。您可以通过以下方式强制实现者始终使用流畅的接口而不是自己实例化MyClass

    • 为 MyClass 提供一个私有构造函数 private MyClass(),只能从内部调用 MyClass
    • 将 MyClass 标记为 sealed 以防止创建暴露公共构造函数的继承者。

    【讨论】:

      【解决方案4】:

      这是不可能的。您不能拥有静态类的实例。由于您已将 MyClass 标记为静态,因此不能有任何实例。不要让它静态:

      public class MyClass
      {
          private StringBuilder builder;
          private StringBuilder RouteBuilder
          {
              get
              {
                  if (builder == null)
                      builder = new StringBuilder();
      
                  return builder;
              }
          }
      
          public MyClass Root()
          {
              RouteBuilder.Append("/");
              return this;
          }
      
          public MyClass And()
          {
              RouteBuilder.Append("and");
              return this;
          }
      
          public MyClass Something()
          {
              RouteBuilder.Append("something");
              return this;
          }
      }
      

      然后你可以链接:

      var result = new MyClass().Root().And().Something();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-20
        • 2013-06-09
        相关资源
        最近更新 更多