Compile Time Reflection in C#
Asked Answered
P

4

22

I frequently write C# code that has to use magic strings to express property names. Everyone knows the problems with magic strings. They are very difficult to refactor, they have no compile time checking, and often they lead to hard-to-diagnose issues. Yet C#/.NET uses them all over the place to represent property/class/method names.

This issue has persisted for years and years, and the only viable solution currently is to use an expression tree which is then parsed at run-time for the property name. This gets you satisfactory compile-time checking, but it complicates the code (requiring parameters of type Expression), and it incurs a run-time cost.

Does anyone know if there has ever been a feature consideration for C#/.NET to add compile-time reflection to overcome this pervasive problem?

It seems like it would be an easy addition to make, it would be a non-breaking change, and it would greatly benefit many developers. The typeof() operator already performs a form of compile-time reflection, so it seems like an operator nameof() (or something similar) would be very complimentary.

In addition, does anyone know of any potential issues with such a feature?

Thanks for the help.

Percentage answered 17/2, 2012 at 20:43 Comment(9)
possible duplicate of Using a lambda expression to avoid using a "magic string" to specify a propertyQuentinquercetin
Also see: Get the property, as a string, from an Expression<Func<TModel,TProperty>>Quentinquercetin
@KirkWoll This is not a duplicate of that question. The question's second paragraph indicates that MgSam is familiar with the expression tree technique; the question is whether there might be a new feature in the works that would allow a new solution to the problem.Sustain
@phoog, true. But this is the solution, as evidenced by this pattern's ubiquitous presence in the BCL.Quentinquercetin
Have you considered using an Inversion of Control container? They use a lot of reflection at the first instance of the application known as the composition root. The configuration is usually done in code or XML.Pym
Add it to the pile of 'potentially useful features in C# that probably won't get implemented because there are many more even more useful features to implement first'.... and move on.Hom
@KirkWoll but it's not particularly helpful to answer the question "is a better solution coming?" by saying "here's the existing solution."Sustain
related: #795708 #4230097Manteau
possible duplicate of Why is there not a `fieldof` or `methodof` operator in C#?Manteau
P
14

Straight from the source - this is a blog post by a C# language designer, and the "User" in this post asks about the same questions as you and is answered. The author says there would be a need to specify a syntax for every metadata item you'd want to ask for and it's not trivial - ie. which overload you want, if you want "info-of" method and the method is overloaded? What if there are generics and explicit interface implementations involved? And so on. It turns out, while it wasn't deemed worthy of implementation in 2009 because of those reasons, we will get it in C# 6 in 2015 - see C# Language Design Notes for Jul 9, 2014 .

Pejsach answered 17/2, 2012 at 20:47 Comment(4)
Well, it is a blog post from a C# language designer about real issues with implementing a "infoof()" operator that works like typeof but for any metadata (method, property etc.). OP asks the same questions as "User" from the article and the "User" gets all the answers.Pejsach
Eric's answer seems to imply that using Expressions has solved the problem. But many of Microsoft's technologies use magic strings to represent classes/properties: ASP .NET (Web Forms and MVC), Silverlight, WPF, Winforms; they all use them. Not to mention 3rd party developers whose libraries you may rely on. And if you look hard enough you'll find core libraries that use them as well. To me this seems like a more pervasive issue (and one that's easier to address) than the issue that the async/await keywords solve.Percentage
I don't think is post answers the why not for properties which are cannot be overloaded.Nasal
While this answer is over a year old and the link is helpful it would be better if you post the essential parts of the answer here, on this site, or your post risks being deleted See the FAQ where it mentions answers that are 'barely more than a link'. You may still include the link if you wish, but only as a 'reference'. The answer should stand on its own without needing the link.Overreact
P
14

In C# 6.0, a new operator, nameof, is being added that will allow you to get the names of properties, classes, fields, events, and variables at compile time.

Link to the design notes

No more reflection for information the compiler already knows at design time!

Percentage answered 30/1, 2015 at 21:0 Comment(0)
B
7

I was having a similar problem. Only recently discovered that .NET Framework 4.5 has a feature called the Caller Info attributes. By using these, you can obtain information about the caller to a method at compile time. You can obtain file path of the source code, the line number in the source code, and the member name of the caller.

public void DoProcessing()
{
    TraceMessage("Something happened.");
}

public void TraceMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("message: " + message);
    Trace.WriteLine("member name: " + memberName);
    Trace.WriteLine("source file path: " + sourceFilePath);
    Trace.WriteLine("source line number: " + sourceLineNumber);
}
Bornstein answered 29/1, 2015 at 14:54 Comment(0)
J
0

Yet C#/.NET uses them all over the place to represent property/class/method names.

First off: I disagree. There are certain frameworks (WebForms, e.g.) that use magic strings all over the place, but the base libraries for C# and .NET tend to avoid such things remarkably well.

Secondly: In many instances where magic strings are used, ReSharper is able to recognize errors. This can help quite a bit.

Finally: What you're asking for may be possible via the Roslyn Compiler, which promises to provide "Compiling as a service."

Joly answered 17/2, 2012 at 20:57 Comment(3)
I agree that core .NET libs stay away from the magic strings, but if you have looked at MVC3 at all, oh man, its MagicString hell :) Thank goodness for ReSharper's ability to tell you if you typed in a wrong controller or action name in a string parameter!Fussbudget
The compiler already knows all of the relevant information during compile time to make this feature possible. From my understanding Roslyn will simply enable 3rd parties to more easily gain similar insights into the code before compile-time.Percentage
@MgSam: Roslyn appears to make it possible to set up your own compilation rules, so it could conceivably allow you to write an expression tree in code that gets converted into a method name, controller name, etc. at compile time.Joly

© 2022 - 2024 — McMap. All rights reserved.