Разве методы расширения C # не позволяют передавать параметры по ссылке?

Действительно ли невозможно создать метод расширения в 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

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

Module Ext
   _
  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 ключевое слово. Есть ли обходной путь для этого?

 LWChris09 нояб. 2015 г., 22:33
Просто для завершениясаке: правильный путьДобавлять" значение перечисления флагаValue = Value Or Arg1 если вы не хотите, чтобы добавлениеMonday два раза ведет себя как добавлениеTuesday, Правильный способ удалить флаг есть.Value = (Value Or Arg1) Xor Arg1

Ответы на вопрос(3)

Однако, хотя это может иметь смысл с технической точки зрения (поскольку метод расширения является просто статическим методом), я думаю, что это не так.это неправильно, потому что методы расширения используются так, как если бы они были методами экземпляра, а методы экземпляра могут 'изменитьthis ссылка.

 Thomas Levesque11 авг. 2009 г., 11:17
вау ... я так и не понял!
 Theodore Zographos02 июн. 2010 г., 15:14
Это'Нечего и говорить, что это отстой большое время для C #.
 Jon Skeet11 авг. 2009 г., 11:08
На самом деле методы экземпляраМожно изменить "этот" в типах значений. Странно, но это правда.
 Camilo Martin15 февр. 2013 г., 07:48
@TheoZographos Я считаю, что это то, чтоздесь, чтобыизбежать плохого кодаКак и многие другие вещи в C #, которые более строгие, чем, скажем, 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

Я думаю, что проблема васНаличие здесь связано с неизменяемостью типов значений. Если бы Будни были ссылочным типом, все бы хорошо. Для неизменяемых типов (структур) способ де-факто - возвращать новый экземпляр с требуемым значением. Например. См. Метод Add в структуре DateTime, он возвращает новый экземпляр DateTime, значение которого = экземпляр DateTime получателя 'значение s + значение параметра.

public DateTime Add( TimeSpan value )
 supercat27 сент. 2012 г., 18:11
В vb можно указать, что метод расширения принимает подразумеваемое (thisMe) какByRef параметр; к сожалению, компилятор затем разрешает передавать ему структуры только для чтения. Одна из основных претензий к изменяемым типам значений заключается в том, чтонечего указывать, какие методы видоизменяютсяthisони позволяют бесполезно вызывать такие методы в экземплярах только для чтения. Я нахожу странным, что разработчики vb.net решили разрешить метод расширения, который принимаетByRef параметр - практически крикЯ МУТИРУЮ АРГУМЕНТ! "- в контексте только для чтения.

что люди ожидают увидеть в 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);
 Thomas Levesque11 авг. 2009 г., 11:11
да, Эрику Липперту это понравится;)
 Mehrdad Afshari11 авг. 2009 г., 11:03
изменяемая неизменяемая структура?
 Sam Harwell11 авг. 2009 г., 11:38
Перечисления являются неизменяемыми значениями, но передача одного по ссылке в качестве параметра this методу расширения заставит его вести себя как изменяемое значение.

Ваш ответ на вопрос