How to get a property name when it uses return returns

How to get the property name of an executable property. If the property uses "return", then MethodBase.GetCurrentMethod (). The name returns the name of the property. But when I use the "yield return" MethodBase.GetCurrentMethod (), the name returns "MoveNext". how to get the name of the executable when it uses return returns?

Code example

class Program { static void Main(string[] args) { var x = myProgram.Something; Console.ReadLine(); } } public class myProgram { public static IEnumerable<string> Something { get { string var = MethodBase.GetCurrentMethod().Name; for (int i = 0; i < 5; i++) { yield return var; } } } } 
+6
source share
3 answers

As you probably noticed, the compiler reorganizes the working methods, and Something returns a private class that implements IEnumerable . Thus, the actual content of your method appears in the MethodBase.GetCurrentMethod method MoveNext this private class, so MethodBase.GetCurrentMethod does not return what it seems should return.

It happens that the name of a private class comes from the name of the original method, which in this case is equal to <Enumerate>d__0 . So, you can parse the original method name from the stack frame.

 static IEnumerable<string> Enumerate() { var method = new StackTrace(true).GetFrame(0).GetMethod().DeclaringType.Name; yield return Regex.Replace(method, @".*<([^)]+)>.*", "$1"); } static void Main(string[] args) { foreach (var @string in Enumerate()) { Console.WriteLine(@string); } } 

This, of course, is a hack and may easily not work in future versions of .NET.

+5
source

As you can probably guess, the problem is that the yield return does a bit of rewriting behind the scenes, much like a using statement or lambda does. It is actually implemented as an enumerator with code that calls yield return , which is part of the MoveNext method in the enumerator.

This is a common problem with using Reflection: it gives you information about the runtime of your executable code, which may not coincide with your idea of โ€‹โ€‹compiling what kind of code it is.

This is a long way to say that there is no easy way to get the information you need. If you would move the yield return further into a separate method, then any code outside this method would not be part of MoveNext , but this may or may not do what you need. You no longer get the name of the method that performs yield return , you get the name of its caller. If thatโ€™s all you care about, it looks like this:

 public IEnumerable<string> Something { get { var x = MethodBase.GetCurrentMethod().Name; return this.DoSomething(x); } } private IEnumerable<string> DoSomething(string x) { for (int i = 0; i < 5; i++) { yield return x; } } 

EDIT: although I doubt this will help you in the short term, for writing this problem has also been resolved using the new C # 5 attributes. Since the CallerMemberName attribute CallerMemberName resolved at compile time and, apparently, before the iterator was rewritten into an enumerator class, it returns the property name:

 public IEnumerable<string> Something { get { var x = this.GetCallerName(); for (int i = 0; i < 5; i++) { yield return x; } } } private string GetCallerName([CallerMemberName] string caller = null) { return caller; } 
+5
source

I would move the iterator to a helper method:

 public class myProgram { public static IEnumerable<string> Something { get { string var = MethodBase.GetCurrentMethod().Name; return GetSomethingInternal(); } } private static IEnumerable<string> GetSomethingInternal() { for (int i = 0; i < 5; i++) { yield return i; } } } 
+1
source

Source: https://habr.com/ru/post/909914/


All Articles