簡體   English   中英

C#擴展方法是否不允許通過引用傳遞參數?

[英]Doesn't C# Extension Methods allow passing parameters by reference?

真的不可能在將實例作為引用傳遞的C#中創建擴展方法嗎?

這是一個示例VB.NET控制台應用程序:

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傳遞的。

並且(幾乎)在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關鍵字。 有什么解決方法嗎?

號在C#,則不能指定任何改性劑(如“出”或ref )比其它this用於擴展方法的第一個參數-你可以為其他人。 雖然不熟悉VB語法,但似乎正在使用聲明性方法來標記擴展方法。

調用它時,您無需指定第一個this參數。 因此,將參數標記為out或ref並沒有意義,因為您無法像通常方法那樣調用它時指定修飾符

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

我認為您在這里遇到的麻煩與值類型不可變有關。 如果“工作日”是一種參考類型,則可以正常工作。 對於不可變類型(結構),事實上的方法是返回具有所需值的新實例。 例如,參見結構DateTime上的Add方法,它將返回一個新的DateTime實例,其值=接收者DateTime實例的值+參數值。

public DateTime Add( TimeSpan value )

Yikes-您正在構建一個可變的不可變結構。 它破壞了人們期望在C#中看到的內容,但是如果必須這樣做,則始終可以直接調用該方法:

Ext.Add(ref value, arg1);

任何擴展方法都可以直接調用。

另外,澄清:

SomeReferenceType value = ...;
SomeReferenceType copy = value;
value.ExtensionMethodByRef(...);
// this failing is semantically ridiculous for reference types, which
// is why it makes no sense to pass a `this` parameter by ref.
object.ReferenceEquals(value, copy);

奇怪的是VB.NET允許這樣做,而C#卻不允許...

但是,盡管從技術角度來看這可能是有道理的(因為擴展方法只是靜態方法),但我認為這樣做不合適,因為擴展方法的使用就好像它們是實例方法一樣,而實例方法可以請勿修改this參考。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM