C# 扩展方法不允许通过引用传递参数吗? [英] Doesn't C# Extension Methods allow passing parameters by reference?

查看:21
本文介绍了C# 扩展方法不允许通过引用传递参数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C#中创建一个将实例作为引用传递的扩展方法真的不可能吗?

Is it really impossible to create an extension method in C# where the instance is passed as a reference?

这是一个示例 VB.NET 控制台应用程序:

Here’s a sample VB.NET console app:

Imports System.Runtime.CompilerServices

Module Module1
  Sub Main()
    Dim workDays As Weekdays

    workDays.Add(Weekdays.Monday)
    workDays.Add(Weekdays.Tuesday)

    Console.WriteLine("Tuesday is a workday: {0}", _ 
      CBool(workDays And Weekdays.Tuesday))
    Console.ReadKey()
  End Sub
End Module

<Flags()> _
Public Enum Weekdays
  Monday = 1
  Tuesday = 2
  Wednesday = 4
  Thursday = 8
  Friday = 16
  Saturday = 32
  Sunday = 64
End Enum

Module Ext
  <Extension()> _
  Public Sub Add(ByRef Value As Weekdays, ByVal Arg1 As Weekdays) 
    Value = Value + Arg1
  End Sub
End Module

注意 Value 参数是通过 ByRef 传递的.

Note the Value parameter is passed ByRef.

并且(几乎)在 C# 中相同:

And (almost) the same in C#:

using System;

namespace CS.Temp
{
  class Program
  {
    public static void Main()
    {
      Weekdays workDays = 0;

      workDays.Add(Weekdays.Monday); // This won't work
      workDays.Add(Weekdays.Tuesday);

      // You have to use this syntax instead...
      // workDays = workDays | Weekdays.Monday;
      // workDays = workDays | Weekdays.Tuesday;

      Console.WriteLine("Tuesday is a workday: {0}", _ 
        System.Convert.ToBoolean(workDays & Weekdays.Tuesday));
      Console.ReadKey();
    }
  }

  [Flags()]
  public enum Weekdays : int
  {
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
  }

  public static class Ext
  {
    // Value cannot be passed by reference? 
    public static void Add(this Weekdays Value, Weekdays Arg1) 
    {
      Value = Value | Arg1;
    }
  }
}

Add 扩展方法在 C# 中不起作用,因为我不能使用 ref 关键字.有什么解决方法吗?

The Add extension method doesn’t work in C# because I can’t use the ref keyword. Is there any workaround for this?

推荐答案

没有.在 C# 中,您不能为扩展方法的第一个参数指定除 this 之外的任何修饰符(如 'out' 或 ref) - 您可以给别人.不熟悉 VB 语法,但似乎使用声明式方法来标记扩展方法.

No. In C#, you cannot specify any modifiers (like 'out' or ref) other than this for the first parameter of an extension method - you can for the others. Not familiar with the VB Syntax but it seems to be using a declarative approach to mark an extension method.

当你调用它时,你不要指定第一个this参数.因此,将参数标记为 out 或 ref 没有意义,因为在调用它时不能像对普通方法那样指定修饰符

When you call it, you do not specify the first this parameter. Hence marking the parameter as out or ref doesnt make sense as You can't specify the modifier when you call it like you'd do for normal methods

void MyInstanceMethod(ref SomeClass c, int data) { ... } // definition

obj.MyInstanceMethod(ref someClassObj, 10);              // call

void MyExtensionMethod(this SomeClass c, int data) {.... } // defn

c.MyExtensionMethod(10);                                 // call

我认为您在这里遇到的麻烦与值类型不可变有关.如果 Weekdays 是一个引用类型,它会正常工作.对于不可变类型(结构),事实上的方法是返回一个具有所需值的新实例.例如.请参阅结构 DateTime 上的 Add 方法,它返回一个新的 DateTime 实例,其值 = 接收方 DateTime 实例的值 + 参数值.

I think the trouble you're having here is related to value types being immutable. If Weekdays was a reference type, it would work out alright. For immutable types (structs), the defacto way is to return a new instance with the required value. E.g. See the Add method on the struct DateTime, it returns a new DateTime instance whose value = receiver DateTime instance's value + param value.

public DateTime Add( TimeSpan value )

这篇关于C# 扩展方法不允许通过引用传递参数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆