【问题标题】:Is it possible to compile a C# method that has non-void return type, but does not return a value?是否可以编译具有非 void 返回类型但不返回值的 C# 方法?
【发布时间】:2014-08-24 18:17:00
【问题描述】:

考虑到以下约束,是否可以以某种方式编译X M() { /*...*/ }

  1. 您不能向M 添加任何其他修饰符。
  2. /*...*/ 不包含returnthrow,您无法更改。
  3. 您不能将重写器添加到编译器管道。
  4. 您可以更改 M 周围的所有其他内容。

这似乎是一个荒谬的问题,但它实际上对 DSL 很有价值。
例如。我可以定义类似task M() {} 的东西,它只是表示这是一项任务,与返回值无关。

【问题讨论】:

  • 如果它返回Task并且有修饰符async,你不需要返回任何东西。可以接受吗?
  • @CodeCaster: "abstract method" 将失败约束 #1。
  • code golf 吗? :D
  • 所以不async Task foo()我接受?

标签: c# syntax dsl


【解决方案1】:

添加来自C# 规范的一些附加信息。

第一段声明方法必须有返回类型,即 void。

方法有一个(可能是空的)参数列表,表示传递给方法的值或变量引用,以及一个返回类型,它指定方法计算和返回的值的类型。如果方法不返回值,则其返回类型为 void。

这第二段指定具有非 void 返回类型的方法必须具有可计算的返回表达式。

方法可以使用 return 语句将控制权返回给它的调用者。在返回 void 的方法中,return 语句不能指定表达式。在返回非 void 的方法中,return 语句必须包含计算返回值的表达式。

尽管规范没有明确声明该方法必须包含 return 语句,但我相信它隐含地这么说。

所以不,根据C# 规范是不可能的。

【讨论】:

    【解决方案2】:

    所以你有一个方法:

    public Foo Bar()
    {
        DoX();
    
        DoY();
    
        DoZ();
    }
    

    这不会编译,因为方法中的唯一路径不返回任何内容。

    鉴于您的限制(基本上:您必须使用标准 C# 编译器按原样编译代码),答案是:不,您无法编译。

    【讨论】:

    • 它基本上是一个 DSL。所以你想让你的用户写task X() { doA(); doB(); doC(); }而不用担心退货。我没有考虑while,但它也有同样的问题——DSL 用户添加它是不自然的。
    • 那为什么要用返回类型来打扰用户呢?
    • 因为逻辑上它不是一个返回类型——它是一个任务的标记。 C# 中是否有更短的方式来描述它?我正在考虑的一个可行的替代方案是task X = () => {...}
    • @AndreyShchekin 这里似乎很清楚你有一个 XY 问题。说明您实际上想要完成的工作,人们可以为您提出设计程序的方法,以便它能够以最佳方式实现您的真正目标。
    • @CodeCaster 实际上这是一个绝对有效的答案,谢谢。我确实将我的问题简化为是/否问题,因为我在是/否答案中看到了一个值。我会考虑如何在当前 SO 规则中提出更大的问题,但无论如何这将是一个单独的问题(如果我什至可以问的话)。
    【解决方案3】:

    也许,

    abstract class Whatever
    {
        public abstract X M<X>();
    }
    

    【讨论】:

    • 如果没有编译器重写,这将无法工作,并且根本不允许正文。与partial btw 相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 2020-09-23
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多