Подтвердить что ты не робот

Разделение/объединение частичных методов

Я понимаю, что частичные методы могут использоваться для разделения определения метода на несколько файлов. Мне любопытно, но если допустимо, чтобы каждое определение метода по нескольким файлам содержало код?

Например, скажем, у меня есть метод private partial void Foo(). Скажем, я определил его в файле A и файле B. Могут ли оба экземпляра иметь код, содержащийся в методе, или только один или другой? Думаю, я был бы удивлен, если бы это было разрешено.

4b9b3361

Ответ 1

Нет, вы не можете. Если бы вы могли, когда вы вызываете Foo(), какой код будет выполняться первым? Если обе версии имели дело (и изменяли) глобальное состояние, было бы очень важно знать порядок выполнения.

Во всяком случае, это не имеет смысла. Итак, нет, вы не можете.

Неприятный пример 1

В качестве простого примера потенциальной гадости неустойчивого поведения, возникающего из такой возможности, предположим, что вы могли бы и предположили, что у вас есть следующий код:

public partial class MyClass {
    private int count = 0;
    public partial void NastyMethod() {
        count++;
    }
}

public partial class MyClass {
    public partial void NastyMethod() {
        Console.WriteLine(count);
    }
}

Когда вы вызываете NastyMethod(), какое значение оно будет печатать? Нет смысла!

Неприятный пример 2

Теперь еще одна странная проблема. Что делать с параметрами? И вернуть значения?

public partial class MyClass2 {
    public partial bool HasRealSolution(double a, double b, double c) {
        var delta = b*b - 4*a*c;
        return delta >= 0;
    }
}

public partial class MyClass2 {
    public partial void HasRealSolution(double a, double b, double c) {
        return false;
    }
}

А теперь, как можно дать смысл этому коду? Какое возвращение следует рассмотреть после вызова HasRealSolution(1, 2, 1)? Как вообще возможно иметь два разных, одновременных, возвращаемых значения * для одного метода? Мы не имеем дело с недетерминированными конечными автоматами!

Для тех, кто наложил бы в этом гипотетическом мире мои несущественные частичные методы, должен быть void, замените return на установку значения для некоторого частного поля для этого класса. Эффект почти тот же.

* Обратите внимание, что здесь я говорю не о одном возвращаемом значении, состоящем из двух значений, таких как Tuple. Я говорю здесь о двух возвращаемых значениях. (???)

Ответ 2

Это действительно комментарий к ответу @Bruno и не может быть полностью релевантным для вопроса:

Решение не допускать, чтобы частичные методы имели множество реализаций, является произвольным решением, принятым при разработке языка. Ваш аргумент является хорошей причиной, по которой вы можете принять решение не допускать такую ​​вещь на своем языке, но на самом деле нет технических ограничений. Вы можете очень легко решить разрешить множественную реализацию и позволить компилятору решить порядок выполнения реализаций. На самом деле, спецификация С# уже имеет случаи с undefined порядком для классов partial:

// A.cs:
partial class Program {
    static int x = y + 42;
    static void Main() {
       System.Console.WriteLine("x: {0}; y: {1}", x, y);
    }
}

// B.cs:
partial class Program {
    static int y = x + 42;
}

Это действительный С# в соответствии с спецификацией С# v3.0, но вывод может быть:

x: 42; y: 84

или

x: 84; y: 42

и компилятору разрешено создавать любой из них. Он даже не генерирует предупреждение.

Язык С# требует частичного метода, чтобы иметь возвращаемый тип void. Подпись частичного метода может быть определена не более одного раза. Аналогично, реализация должна определяться не более одного раза.

Ответ 3

Нет. Только одна версия частичного метода может содержать код. Определение более чем одной реализации частичного метода с реализацией приведет к ошибке компилятора.

Ответ 4

Это невозможно. Вы определяете подпись в одном месте и реализацию в другом месте.

Подробнее см. MSDN.

Ответ 5

Нет, это невозможно. Кроме того, у вас есть небольшое недоразумение. Целью частичных методов является не "разделение определения метода на несколько файлов".

Скорее, partial method предназначен для разделения определения класса на несколько файлов. Это полезно, особенно с автоматически сгенерированным кодом, поскольку он позволяет вам определять "необязательные" методы, которые вы можете реализовать, но также свободно игнорировать.

Ответ 6

Как указал один из респондентов, нет никаких технических причин для исключения нескольких реализаций частичных методов в нескольких частях частичного класса. Сейчас в моде, даже в соответствии с Microsoft DOC, создавать сборки, которые будут выполняться в Silverlight, а также работать под полной версией CLR, в зависимости от того, какие файлы включены. Собственные примеры Microsoft включают частичные определения методов в файлах, совместимых с Silverlight, с их реализациями, включенными в другие файлы, которые будут включены в сборку CLR.

Конечно, если было разрешено несколько реализаций, разработчик должен был бы знать, что вызывающий порядок не является детерминированным. Одним примером может служить метод, в котором была сделана единственная ссылка на bool, которая указывала, что текущая среда способна выполнять "что-то".

Пример:

/// <summary>
/// Method will determine whether a type is serializable.
/// </summary>
/// <param name="type">
/// The Type to be checked for serializability.
/// </param>
/// <param name="serializable">
/// ref variable to be set to <c>true</c> if serializable. If
/// <paramref name="serializable"/> is already <c>true</c>, the
/// method should simply return.
/// </param>

static partial void IsTheTypeSerializable (тип типа, ref Boolean serializable);

Этот метод МОЖЕТ использоваться в реализации структуры, которая включает в себя несколько вариантов сериализации типов, в зависимости от того, какие части частичных классов смешиваются и какие сериализаторы включены. Даже если существует только одна реализация (все, что может быть в соответствии с правилами компилятора), реализация должна следовать логике, описанной выше в DOC метода, поскольку нет гарантии того, в какой точке определяющей части метод будет вызывается. Если допускалось несколько реализаций, общая логика должна гарантировать, что результат не будет зависеть от порядка вызова реализаций.

В наших рамках мы фактически используем загружаемых делегатов для выполнения анализа сериализации в разных сценариях. Тем не менее, было бы действительно удобно иметь несколько реализаций, разрешенных именно для этого сценария.

Мы предполагаем, что Microsoft опасается хаоса, который возникнет, если начинающие разработчики будут отключены, чтобы использовать эту опасную функцию. Нужно знать, что с этим связано.

Ответ 7

Вы не можете объединить методы, но вы можете настроить цепочку с помощью Partial Methods. Если вы хотите избежать перекодирования кода, это вариант. Я не говорю, что это отличный вариант, но это вариант.

public partial class MyClass {
    private int count = 0;
    public partial void NastyMethod() {
        count++;
    }
}

public partial class MyClass {
    public partial void NastyMethod() {
        Console.WriteLine(count);
    }
}

Изменяется на.

public partial class MyClass {
    private int count = 0;
    public partial void NastyMethod() {
        count++;
        OnNastyMethodExecuted(count);
    }

partial void OnNastyMethodExecuted(int Value);
}

public partial class MyClass {
    partial void OnNastyMethodExecuted(int value) {
        Console.WriteLine(value);
    }
}
  • Частичные методы указываются частичным модификатором.
  • Частичные методы должны быть частными.
  • Частичные методы должны возвращать void.
  • Частичные методы должны быть объявлены только в частичных классах.
  • Частичные методы не всегда имеют реализацию.
  • Частичные методы могут быть статическими и обобщенными.
  • Частичные методы могут содержать аргументы, включая ref, но не из.
  • Вы не можете сделать делегат частичным методом.

Правила из:

https://www.codeproject.com/Articles/30101/Introduction-to-Partial-Methods