开发者

Splitting/Combining Partial Methods

开发者 https://www.devze.com 2022-12-16 15:22 出处:网络
I understand partial methods can be used to split the definition of a method across multiple files. I\'m curious though if it\'s permissible to have each definition of a method across multiple files c

I understand partial methods can be used to split the definition of a method across multiple files. I'm curious though if it's permissible to have each definition of a method across multiple files contain code?

For example, say I have a method private partial void Foo(). Let's s开发者_Python百科ay I've got it defined in file A and file B. Can both instances have code contained in the method, or just one or the other? I guess I'd be surprised if this were permitted.


No, you can't. If you could, when you call Foo(), which code would execute first? If both versions were dealing with (and modifying) global state, it would be very important to know the order of execution.

Anyway, it makes no sense. So no, you can't.

Nasty example 1

As a simple example of the potential nastiness of the erratic behavior emerging from such a possibility, suppose you could, and suppose you had the following code:

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

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

When you call NastyMethod(), what value would it print? No sense!

Nasty example 2

Now another strange problem. What to do with parameters? And return values?

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;
    }
}

And now, how could one possibly give a sense to this code? Which return should we consider after calling HasRealSolution(1, 2, 1)? How is it ever conceivable to have 2 different, simultaneous, return values* for a single method? We are not dealing with nondeterministic finite automata!

To those who would impose that in this hypothetical world my inexistent partial methods should be void, replace the returns with setting a value on some private field to that class. The effect is almost the same.

* Note that what I'm talking here is not a single return value composed of two values, such as a Tuple. I'm talking here about TWO return values. (???)


This is really a comment to @Bruno's answer and may not be completely relevant to the question:

The decision to not allow partial methods to have multiple implementations is an arbitrary decision made in the design of the language. Your argument is a good reason why you might decide against allowing such a thing in your language but there isn't really a technical limitation. You can very easily decide to allow multiple implementation and let the compiler decide the order of execution of implementations. Actually, C# specification already has cases with undefined order for partial classes:

// 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;
}

This is valid C# according to the C# Specification v3.0 but the output can be:

x: 42; y: 84

or

x: 84; y: 42

and the compiler is allowed to generate either of them. It doesn't even generate a warning.

The C# language requires a partial method to to have a void return type. The partial method signature can be defined at most once. Likewise, the implementation should be defined at most once.


No. Only a single version of a partial method may contain code. Defining more than one implementation of a partial method with an implementation will result in a compiler error.

  • http://msdn.microsoft.com/en-us/library/wa80x488.aspx


No, this is not possible. Also, you have a slight misunderstanding. The purpose of partial methods is not to "split the definition of a method across multiple files".

Rather, a partial method is designed to split the definition of class across multiple files. This is helpful, especially with automatically generated code, since it lets you define "optional" methods that you are free to implement, but also free to ignore.


As one of the responders has indicated, there is no technical reason for the exclusion of multiple partial method implementations in multiple parts of a partial class. It is now in vogue, even according to Microsoft DOCs to create assemblies that will run within Silverlight and can also run under the full CLR, depending on what files are included. Microsoft's own examples include partial method definitions in Silverlight compatible files with their implementations included in other files that would be included in a CLR build.

Of course, if multiple implementations were allowed, the developer would have to be aware of the fact that the calling order is non-deterministic. One example would be the case of a method that took a single reference to a bool that indicated that the current environment was capable of doing "something".

An example:

/// <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(Type type, ref Boolean serializable);

This method COULD be used in the implementation of a framework that includes multiple options for serialization of types, depending on what parts of partial classes are mixed in and what serializers are included. Even when there is only a single implementation (all that there can be under the compiler's rules), the implementation must follow the logic described in the method DOCs above, since there is no guarantee of at what point in the defining part the method will be invoked. If there were multiple implementations allowed, the overall logic must guarantee that the result would not depend on the order of invocation of the implementations.

In our framework, we actually use loadable delegates to perform the serializability analysis for different scenarios. However, it would be convenient, indeed, to have multiple implementations allowed for precisely this scenario.

We surmise that Microsoft feared the chaos that would ensue if novice developers were turned loose to use this dangerous feature. One needs to know what one is about with such a thing.


That is not possible. You define the signature in one place, and the implementation in another place.

For details, see MSDN.


You can't merge the methods but you can setup a chain using Partial Methods. If you want to avoid code weaving, this is an option. I'm not saying it's a great option but it's an option.

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

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

Changes to.

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);
    }
}

The rules before C# 9 and code generators were added:

  • Partial methods are indicated by the partial modifier.
  • Partial methods must be private.
  • Partial methods must return void.
  • Partial methods must only be declared within partial classes.
  • Partial methods do not always have an implementation. 
  • Partial methods can be static and generic.
  • Partial methods can have arguments including ref but not out. 
  • You cannot make a delegate to a partial method.

Rules after C#9:

  • Partial methods can have return types.

  • Partial methods can have out params.

  • Partial methods can have access modifiers.

  • However, if they do, then they must have an implementation.

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

0

精彩评论

暂无评论...
验证码 换一张
取 消