【问题标题】:creating an alias for a function name in C#在 C# 中为函数名创建别名
【发布时间】:2020-08-07 23:13:52
【问题描述】:

我想为 C# 中的函数名称创建一个别名。

除了函数重载还有什么办法吗?

public class Test
{
    public void A()
    {
        ...
    }
}

我想在下面调用 B 替换 A。

var test = new Test();
test.B();

【问题讨论】:

  • 另外,如果你重载了一些东西,你不会给它起别名,因为它是同一个标识符。
  • 您正在向我们提供一个(损坏的?)解决方案,以解决您遇到的一些问题。如果您告诉我们您要解决的问题是什么,我们可能会做得更好。
  • 所以,真正的答案是:No, C# does not have method aliasing。为什么很难给出直截了当的答案?

标签: c# alias


【解决方案1】:

我很惊讶没有人提到代表。它可能与 C# 中的方法别名一样接近:

class DelegaTest
{
    public string F()
    {
        return null;
    }

    public string F(int arg)
    {
        return arg.ToString();
    }

    public void G(int arg1, int arg2)
    {
    }

    /// <summary>
    /// Delegate for `string F()`
    /// </summary>
    public Func<string> D1 => F;

    /// <summary>
    /// Delegate for `string F(int arg)`
    /// </summary>
    public Func<int, string> D2 => F;

    /// <summary>
    /// Delegate for `void G(int arg1, int arg2)`
    /// </summary>
    public Action<int, int> E => G;
}

【讨论】:

  • 您能否另外展示:1) 支持重载 2) 带参数,但类型为 void
  • @T.Todua,我添加了一些示例并进行了修改以使用 C# 7.0(粗箭头)。
  • 与级联调用的单独方法相比,这种方法似乎没有优势。除了这些方法会比这更有效,因为Func&lt;&gt;Action&lt;&gt; 分配了常规方法不会分配的额外内存。
  • 很好,但是有没有办法将它与传递给函数的可选参数一起使用?
  • public Func> React => SetBillStatusAsync; public async Task SetBillStatusAsync(string itemId, OrderPaymentStatus status) { return await _api.SetBillStatusAsync(itemId, status); }
【解决方案2】:

您可以使用extension method

public static class Extensions 
{
    public static void B(this Test t)
    {
       t.A();
    }
}

但它不是别名。它是一个包装器。


编辑
ps:我同意评论者对您问题的看法,如果我们知道您真正想要做什么,如果我们了解您要解决的问题,我们将能够提供更好的答案。

我真的不明白产生上述扩展方法的意义。

【讨论】:

  • 不幸的是,如果您想要别名的方法是静态的,这将没有帮助。但是这种方法对于实例方法很有效,特别是如果出于兼容性原因它们只是语法糖,您可以将它们放在可选导入的命名空间中。
【解决方案3】:

这太老了,但我有一个关于为什么人们可能想要别名方法名称的回应。它一直在发生。因为一些开发者给一个方法起一个没有任何意义的名字,或者它根本没有准确地描述方法的目的。该方法在一个旧的、经验丰富的解决方案中被多次调用。因此,与其执行由于名称不佳的方法而无法证明的大型重构和重新测试,不如简单地给它一个有意义的别名。这样,新代码将来会正确读取。

即保存了一个网格控件,并且有一个方法名为 IsReferenceSelectedSendEmail。该名称暗示该方法将识别用户在网格中选择的引用是否为 SendEmail。该方法真正做的是遍历所有引用并识别其中是否有任何一个是 SendEmail。

简单的解决方案。将方法别名为 AnyReferenceIsSendEmail 以便将来的代码可以正确读取: if ( AnyReferenceIsSendEmail() )...

现在,如果我们可以只使用关键字“除非”来否定 if 条件。

国际海事组织

【讨论】:

    【解决方案4】:

    实际上,函数别名更多地是 C# 术语中的 委托(就像 C++ 中的函数指针)。这是一个:

    public class Test
    {
        public void Test()
        {
            B += A;
        }
    
        public void A()
        {
            ...
        }
    
        public Action B;
    }
    

    但您必须将其称为 B.Invoke(),因为它是无参数的。如果它有一个或多个参数,这不是问题。

    【讨论】:

    • 其实不用Invoke()也可以打电话给B。就Test.B();
    【解决方案5】:

    C# 是面向对象的语言,因此您不能创建“函数别名”。您只能使用类进行操作。如前所述,您可以使用扩展方法扩展类,也可以创建派生类并在其中创建新方法,这将调用派生方法:

        class Test
        {
            public void A()
            {
                MessageBox.Show("Function A");
            }
        }
    
        class Test2: Test
        {
            public void B()
            {
                A();
            }
        }
    

    但是如果你想在你的初始类Test 上调用B(),你只有一种方法——创建扩展方法。

    【讨论】:

      【解决方案6】:

      这行得通。

      class Program
      {
          delegate void B();
          static Test t = new Test();
          static B b = t.A;
      
          static void Main(string[] args)
          {
              b();
          }
      
      }
      
      class Test
      {
          public void A()
          {
          }
      }
      

      【讨论】:

        【解决方案7】:

        在这篇文章中有几个 cmet 关于为什么有人会想要这样做。我目前正在为图形项目实现 Vector 类型,我使用的需求文档指的是 Vector 的大小/长度可互换。为了效率起见,我宁愿不在 Length() 方法中包装 Magnitude() 方法,但如果结构能够理解这两个术语,这似乎会很好。

        Christian Davén 提到的委托方法可能是我能看到的最有效的方法,但最好将文档简单地添加到方法的块中:

        /// <summary>
        /// Calculate the magnitude / length of a vector, including the W component.
        /// </summary>
        /// <remarks>
        /// This calculation will break down if you try to take the magnitude of a point.
        /// </remarks>
        /// <returns>The magnitude / length of the vector.</returns>
        public float Magnitude()
        {
            return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
        }
        

        【讨论】:

          【解决方案8】:

          我知道这是旧的,但我确实认为这是一个相关的问题,并且可以使用 C# 3.0 中可用的委托/Lambda 表达式很容易地解决,如果我没记错的话,这在 OP 的时候就已经存在了。

          假设我们正在创建一个游戏,该游戏需要我们登录到 Xbox Live 并有两个按钮 - 一个用于登录,一个用于切换用户。一个名为 SignIn 的函数将同时处理它们,但这会导致添加 onclick 处理程序时的可读性差。

          幸运的是,使用委托和 Lambda 表达式可以轻松解决此问题。

          这是SignIn 函数:

          public static async void SignIn(object coreDispatcher)
          {
          ...
          }
          

          这是创建“别名”的 Lambda 表达式

          public static async void SwitchUser(object param) => SignIn(param);
          

          现在我可以调用SignInSwitchUser 并使用相同的代码,但提供更有意义的代码

          【讨论】:

          • 首先欢迎来到 StackOverflow。您的 SignInSwitchUser 示例使用了许多比 C# 3 晚引入的语言特性(例如:异步、表达式主体成员)。请对齐您的示例代码。
          猜你喜欢
          • 1970-01-01
          • 2015-05-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-11
          • 1970-01-01
          相关资源
          最近更新 更多