C# - Can't declare delegate within a method

2019-04-20 07:26发布

问题:

I'm really blanking out here.

I'm wondering why I can't declare a delegate type within a method, but rather I have to do it at a class level.

namespace delegate_learning
{
    class Program
    {
        // Works fine
        public delegate void anon_delgate(int i);

        static void Main(string[] args)
        {
            HaveFun();
            Console.Read();
        }

        public static void HaveFun()
        {
            // Throws an error :/
            //delegate void anon_delgate(int i);

            anon_delgate ad = delegate(int i) { Console.WriteLine(i.ToString());};
        }


    }
}

Edit: I'm researching Lambda Expressions and backing up into how it was before Lambdas, for my own personal knowledge.

回答1:

// Throws an error :/
delegate void anon_delgate(int i);

It throws an error, because it's a type definition, not a variable declaration. Any type definition is not allowed inside method. It's allowed only at class scope, or namespace scope.

namespace A
{
   delegate void X(int i); //allowed
   public class B
   {
         delegate void Y(int i); //also allowed
   }
}

By the way, why don't you write this:

anon_delgate ad = i => Console.WriteLine(i.ToString());

It's called lambda expression.



回答2:

You can't declare any type inside a method. So let's consider the question "why can I not declare a type inside a method in C#?"

The answer to questions of this form is always the same. In order for you to be able to do something in C#, the following things all have to happen:

  • Someone has to think of the feature
  • Someone has to design the feature
  • Someone has to write the specification of the feature
  • Someone has to implement that specification
  • Someone has to test the implementation
  • Someone has to document the feature (and translate the documentation into a dozen different languages.)
  • Somehow the implementation code has to get into a "vehicle" by which it can be shipped to customers.

So far, of the things on that list only the first one has happened. The rest of them haven't ever happened, so you can't use that feature in C#.

You seem to imply that the default state of a feature is "implemented" and that we have to come up with some reason to make it not implemented. I assure you that's not the case; the default state of all possible features is "not implemented", and we have to have a justification for spending the time, money and effort it takes to implement a feature. So far no one has made a compelling case that local type declarations are worthwhile; if you'd like to try to make a compelling case, I'd love to hear it.



回答3:

Declaring a delegate inside a method would be like declaring a class inside a method because the compiler rewrites the delegate declaration onto a class declaration.

This is why you can't do this while it's perfectly valid do assign to a delegate type.



回答4:

Being able to create arbitrary delegates any time you want is useful, but giving them distinct but anonymous types seems far less useful.

With or without lambdas, you could just replace anon_delgate ad with Action<int>. Since nobody outside method can see anon_delegate, its existence doesn't add extraordinary value. You want to define the delegate type locally, but you could encode any information about the purpose of the delegate inside the variable's name rather than in the variable's type. The dozens of already defined* Action and Func delegates make it very rare that you'll be unable to find a delegate that suits your needs.

In short, I see this feature as adding some heavy costs per Eric, but don't see it as adding enough benefits to offset those costs, nevermind offsetting the additional confusion that comes from providing another feature that might confuse developers.

This feature doesn't add any expressive power to the language, its nonexistence is easily worked around, and I think would waste more developer time (by making C# harder to learn/use) than it would save.

*(well, less of them in older versions of C#, but asking why a feature isn't in an older version of C# when it could be useful is pretty unexciting when the answer is, "wow, that is useful. We added it to the next version.")



回答5:

Why don't you just use lambda expressions?

Action<int> ad = i => Console.WriteLine(i.ToString());


回答6:

Because a delegate is a public method signature intended for a user of the class to comply with on their end. It's a way of saying "if you expose this method with these parameters, I can call it when necessary".

Method internals are not exposed outside of the class - just the signature - so declaring a method signature within what is private to the class doesn't make sense.