【问题标题】:using extension methods on int在 int 上使用扩展方法
【发布时间】:2023-03-10 18:15:01
【问题描述】:

我正在阅读有关扩展方法的信息,并与他们胡闹 看看它们是如何工作的,我尝试了这个:

namespace clunk {
    public static class oog {
        public static int doubleMe(this int x) {
            return 2 * x;
        }
    }

    class Program {
        static void Main() {
            Console.WriteLine(5.doubleMe());
        }
    }
}

它按预期工作,使用 doubleMe 方法成功扩展 int,打印 10。

接下来,作为一个老 C 的人,我想知道我是否可以这样做:

namespace clunk {
    public static class BoolLikeC {
        public static bool operator true(this int i)  { return i != 0; }
        public static bool operator false(this int i) { return i == 0; }
    }

    class Program {
        static void Main() {
            if ( 7 ) {
                Console.WriteLine("7 is so true");
            }
        }
    }
}

我认为,如果前者可行,那么后者应该努力做到这一点 在布尔上下文中使用的 int 会调用 int 上的扩展方法,检查一下 7不等于0,返回true。但相反,编译器甚至不喜欢 稍后的代码,并将红色波浪线放在这两个下面,并说“预期类型”。 为什么这不起作用?

【问题讨论】:

  • 完全猜测,但是,您是否尝试过在运算符上使用隐式键?
  • 好吧,这不会编译,因为您不能使用扩展方法来创建重载运算符。您可以也许创建一个可以工作的BoolLikeC 类,但我认为这样做不是一个好主意。如果你想写 C,那么就写 C。C# 被设计成使这种东西非法是有充分理由的。如果要确定一个整数是否为 0,请使用相关的语言构造。

标签: c# extension-methods


【解决方案1】:

非常聪明!不错的尝试,但遗憾的是我们没有实现“扩展一切”,只是扩展方法。

我们考虑过实现扩展属性、扩展操作符、扩展事件、扩展构造函数、扩展接口等等,但它们中的大多数都没有足够的吸引力使其成为 C# 4 或即将发布的 C# 版本。我们已经为您提到的那种事情设计了一种语法。我们在扩展属性上走得更远;我们几乎在 C# 4 中获得了扩展属性,但最终没有成功。悲伤的故事就在这里。

http://blogs.msdn.com/b/ericlippert/archive/2009/10/05/why-no-extension-properties.aspx

所以,长话短说,没有这样的功能,但我们会在假设的未来版本的语言中考虑它。

如果您确实喜欢non-zero-means-true的复古 C 约定,您当然可以在 int 上创建一个“ToBool()”扩展方法。

【讨论】:

  • 现在每当我想到 bool 扩展运算符时,看到问题中的示例让我畏缩......
【解决方案2】:

扩展方法就是这样——方法。
您不能制作扩展运算符或属性。

如果可能的话,这将导致代码非常难以阅读。
如果您不熟悉代码库,几乎不可能弄清楚if (7) 的含义。

【讨论】:

    【解决方案3】:

    正如其他人所说,C# 中没有扩展运算符。

    你能得到的最接近的方法是在自定义“桥”类型上使用隐式转换运算符,冒着导致许多讨厌的错误的风险:

    // this works
    BoolLikeC evil = 7;
    if (evil) Console.WriteLine("7 is so true");
    
    // and this works too
    if ((BoolLikeC)7) Console.WriteLine("7 is so true");
    
    // but this still won't work, thankfully
    if (7) Console.WriteLine("7 is so true");
    
    // and neither will this
    if ((bool)7) Console.WriteLine("7 is so true");
    
    // ...
    
    public struct BoolLikeC
    {
        private readonly int _value;
        public int Value { get { return _value; } }
    
        public BoolLikeC(int value)
        {
            _value = value;
        }
    
        public static implicit operator bool(BoolLikeC x)
        {
            return (x.Value != 0);
        }
    
        public static implicit operator BoolLikeC(int x)
        {
            return new BoolLikeC(x);
        }
    }
    

    【讨论】:

      【解决方案4】:

      很遗憾,您无法通过扩展方法在类型上引入新的运算符,或实现对现有运算符的支持。

      你想做的,基本上做不到。

      引入新运算符的唯一方法是将它们放入其中一种涉及的类型中。对于二元运算符,您可以将它们放在您自己的类型中,前提是您的类型是两者之一,对于一元类型,您需要将运算符放在类型本身中。

      由于您无法以任何方式扩展int,因此您不能这样做。

      【讨论】:

        【解决方案5】:

        Console.WriteLine(5.doubleMe());

        等价于

        Console.WriteLine(oog.doubleMe(5));

        鉴于此,您可以了解为什么 if ( 7 ) 不起作用。

        扩展方法只不过是语法。

        附带说明,因为它是语法,所以您可以在 null 变量上调用扩展方法,因为它转换为普通方法调用,并且方法可以采用空参数。

        【讨论】:

          【解决方案6】:

          很遗憾不能使用扩展方法来添加操作符,C#中的隐式类型转换是作为操作符实现的。

          【讨论】:

            【解决方案7】:

            在第一个实例中,您正在编写扩展方法 - 例如扩展int 数据类型的功能。在第二个代码集中,您试图覆盖 bool 运算符。这是两个完全不同的东西。

            【讨论】:

              猜你喜欢
              • 2011-11-08
              • 2012-01-16
              • 2015-03-12
              • 2013-05-25
              • 1970-01-01
              • 1970-01-01
              • 2011-09-29
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多