Can There Be Private Extension Methods?

后端 未结 6 1180
Happy的楠姐
Happy的楠姐 2021-01-07 16:01

Let\'s say I have a need for a simple private helper method, and intuitively in the code it would make sense as an extension method. Is there any way to encapsulate that hel

相关标签:
6条回答
  • 2021-01-07 16:28

    Is there a compelling reason for this requirement?

    That's the wrong question to ask. The question asked by the language design team when we were designing this feature was:

    Is there a compelling reason to allow extension methods to be declared in nested static types?

    Since extension methods were designed to make LINQ work, and LINQ does not have scenarios where the extension methods would be private to a type, the answer was "no, there is no such compelling reason".

    By eliminating the ability to put extension methods in static nested types, none of the rules for searching for extension methods in static nested types needed to be thought of, argued about, designed, specified, implemented, tested, documented, shipped to customers, or made compatible with every future feature of C#. That was a significant cost savings.

    0 讨论(0)
  • 2021-01-07 16:33

    I believe it is the way they implemented the compiling of the Extensions Methods.

    Looking at the IL, it appears that they add some extra attributes to the method.

    .method public hidebysig static int32 GetNext(int32 i) cil managed
    {
        .custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor()
        .maxstack 2
        .locals init (
            [0] int32 num)
        L_0000: nop 
        L_0001: ldarg.0 
        L_0002: ldc.i4.1 
        L_0003: add 
        L_0004: dup 
        L_0005: starg.s i
        L_0007: stloc.0 
        L_0008: br.s L_000a
        L_000a: ldloc.0 
        L_000b: ret 
    }
    

    There is probably some very fundamental that we are missing that just doesn't make it work which is why the restriction is in place. Could also just be that they wanted to force coding practices. Unfortunately, it just doesn't work and has to be in top-level static classes.

    0 讨论(0)
  • 2021-01-07 16:34

    While the question is corretly answered by Alexei Levenkov I would add a simple example. Since the extension methods - if they are private - has no much point, because unreachable outside the containing extension class, you can place them in a custom namespace, and use that namespace only in your own (or any other) namespaces, this makes the extension methods unreachable globally.

    namespace YourOwnNameSpace
    {
        using YourExtensionNameSpace;
    
        static class YourClass
        {
            public static void Test()
            {
                Console.WriteLine("Blah".Bracketize());
            }
        }
    }
    
    namespace YourOwnNameSpace
    {
        namespace YourExtensionNameSpace
        {
            static class YourPrivateExtensions
            {
                public static string Bracketize(this string src)
                {
                    return "{[(" + src + ")]}";
                }
            }
        }
    }
    

    You have to define your namespace twice, and nest your extension namespace inside the other, not where your classes are, there you have to use it by using. Like this the extension methods will not be visible where you are not using it.

    0 讨论(0)
  • 2021-01-07 16:40

    I believe the best you can get in general case is internal static class with internal static extension methods. Since it will be in your own assembly the only people you need to prevent usage of the extension are authors of the assembly - so some explicitly named namespace (like My.Extensions.ForFoobarOnly) may be enough to hint to avoid misuse.

    The minimal internal restriction covered in implement extension article

    The class must be visible to client code ... method with at least the same visibility as the containing class.

    Note: I would make extension public anyway to simplify unit testing, but put in some explicitly named namespace like Xxxx.Yyyy.Internal so other users of the assembly would not expect the methods to be supported/callable. Essentially rely on convention other than compile time enforcement.

    0 讨论(0)
  • 2021-01-07 16:41

    This is taken from an example on microsoft msdn. Extesnion Methods must be defined in a static class. See how the Static class was defined in a different namespace and imported in. You can see example here http://msdn.microsoft.com/en-us/library/bb311042(v=vs.90).aspx

    namespace TestingEXtensions
    {
        using CustomExtensions;
        class Program
        {
            static void Main(string[] args)
            {
                var value = 0;
                Console.WriteLine(value.ToString()); //Test output
                value = value.GetNext(); 
                Console.WriteLine(value.ToString()); // see that it incremented
                Console.ReadLine();
            }
        }
    }
    
    namespace CustomExtensions 
    {
        public static class IntExtensions
        {
            public static int GetNext(this int i)
            {
                return i + 1;
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-07 16:48

    This code compiles and works:

    static class Program
    {
        static void Main(string[] args)
        {
            var value = 0;
            value = value.GetNext(); // Compiler error
        }
    
        static int GetNext(this int i)
        {
            return i + 1;
        }
    }
    

    Pay attention to static class Program line which was what the compiler said is needed.

    0 讨论(0)
提交回复
热议问题