Replies: 31 comments 53 replies
-
If we do this, In other words, it should return what you type in C# to refer to the object, not the CLR representation. |
Beta Was this translation helpful? Give feedback.
-
I feel uneasy promoting my own framework here, but I made something for this a long time ago. It isn't perfect, but it will handle many common cases. You can call:
And get "myVariable.MyList[i].MyProperty" out. It won't cover full type names, though. I had something for that too, but I never ported it to my current code base. https://github.com/jjvanzon/JJ.Framework/blob/master/Framework/Reflection/ExpressionHelper.cs |
Beta Was this translation helpful? Give feedback.
-
@janjoostvanzon That's really cool! Now if only it was a compile-time constant and could be used in an attribute... |
Beta Was this translation helpful? Give feedback.
-
@jnm2 That's what I thought when I made it. That would give better performance, even though I did try to make it perform well without sacrificing reliability. Still it cannot be faster than a literal string. |
Beta Was this translation helpful? Give feedback.
-
There is a proposal to make Also #522 suggests to add a shorthand for |
Beta Was this translation helpful? Give feedback.
-
@alrz not really as it would be nice to be able to refer to sub-namespaces and members as well (yes, I remember dotnet/roslyn#1653). I am mostly after shortest possible syntax but compile-time evaluation is also important. |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
This stuff is ridiculous, an extra keyword just for something small like this? just add a method like Class.fullnameof |
Beta Was this translation helpful? Give feedback.
-
The point of it being a keyword is that it could be used as a constant. Invoking a method on the I believe there is a separate proposal for having the compiler consider certain expressions on |
Beta Was this translation helpful? Give feedback.
-
ok but this really sounds more like a problem about c# attributes. Why else require all these new keywords |
Beta Was this translation helpful? Give feedback.
-
The arguments used in attributes are required to be constants and embeddable directly in the assembly metadata. That is a limitation of the CLR and not specifically of the C# language. When the CLR actually instantiates the attribute it expects that the embedded constant matches the type of the constructor parameter or property so the C# compiler can't embed any alternatives, let alone something that represents an expression to be evaluated at runtime. The best the C# compiler could do is to introduce a form of constant expressions ( |
Beta Was this translation helpful? Give feedback.
-
This would be mighty convenient in some cases, especially when defining an I'm currently doing this: // I'm repeating the full namespace in each case, even though I don't strictly need to, for better safety if/when refactoring moves things around.
[EventSource(Name =
nameof(Company) + "." +
nameof(Company.ProductUmbrella) + "." +
nameof(Company.ProductUmbrella.Product) + "." +
nameof(Company.ProductUmbrella.Product.Feature) + "." +
nameof(Company.ProductUmbrella.Product.Feature.Module) + "." +
nameof(Company.ProductUmbrella.Product.Feature.Module.ETWEventSource))]
public class ETWEventSource : EventSource
{ I'd be delighted to be able to do this: [EventSource(Name = fullnameof(ETWEventSource))]
public class ETWEventSource : EventSource
{ |
Beta Was this translation helpful? Give feedback.
-
This should work for namespaces too! I.e. |
Beta Was this translation helpful? Give feedback.
-
How does this work with generics? |
Beta Was this translation helpful? Give feedback.
-
This would be most usable in Obsolete attribute. |
Beta Was this translation helpful? Give feedback.
-
Probably because $ operator is just really string.Format in disguise and attributes needs const strings. |
Beta Was this translation helpful? Give feedback.
-
@npodbielski |
Beta Was this translation helpful? Give feedback.
-
Cool. I didn't know. Anyway still, if we are talking about refactoring tools, IMHO it would complicate things (i.e. refactor by conversion $ to string.Format) because tool would have to inspect if $ is not used in attribute. |
Beta Was this translation helpful? Give feedback.
-
honestly I'd be happy if the System.Console.WriteLine(nameof(System.String));
System.Console.WriteLine(nameof(String)); outputs
I'd much rather see it output
but that could open a whole can of worms... so I can very much live with |
Beta Was this translation helpful? Give feedback.
-
I'd be happy if |
Beta Was this translation helpful? Give feedback.
-
Perhaps a corollary to this one, I have a case where namespace Foo
{
class Bar { }
}
// ...
const string barNameSpace = namespaceof(Bar); // "Foo" const string I mean, if we can discover |
Beta Was this translation helpful? Give feedback.
-
It would also be nice if the character(s) separating the parts of the identifier's fully-qualified name could be configured (rather than using namespace Foo.Bar {
class Baz {
void DoStuff() { }
}
}
// ...
nameof(DoStuff, '/') // Returns Foo/Bar/Baz/DoStuff |
Beta Was this translation helpful? Give feedback.
-
I suggest add a new operator called example:
|
Beta Was this translation helpful? Give feedback.
-
I just upvoted this because of a particular source generation problem. (edit: @CyrusNajmabadi pointed out that you can get the value entered via the SyntaxNode. I'd still like this feature, but it is no longer blocking - further comment below) (The use case here is extending System.CommandLine Dragonfruit, especially to subcommands. Each method represents a command, each parameter an option or argument. The generation creates types for the commands, and if the method is named Main and there is no entry point, creates the entry point. This is the way Dragonfruit works today, except it does not have subcommands and generation is done in an MSBuild target.) I need to link a bunch of methods together. The syntax I like best puts the name of the subcommand method in a params array on the attribute:
If we To make generation more efficient, I would love it if we carried the symbol pointed to by |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi I found the nameof to be the constant string that was the name (without the type). I would love to solve that - I definitely could have overlooked something. |
Beta Was this translation helpful? Give feedback.
-
Yep, thanks to @CyrusNajmabadi I checked my work and I did overlook something and have this fixed. If I require that all methods be in the current namespace or fully qualified (I think I have to check for both if the first fails), I can get the fully qualified name and do the lookup it appears. I would still like to see this feature, but I am unblocked. Thanks again!! |
Beta Was this translation helpful? Give feedback.
-
EditLike many people in this thread I wanted a way of converting chained member access into a string. .NET 6 added CallerArgumentExpression which lets you create a workaround version of Exampleusing System.Runtime.CompilerServices;
// value: "value"
// fullpath: "nameof(HttpResponseMessage.Content.Headers)"
var fullString = StringOf(nameof(HttpResponseMessage.Content.Headers));
// Prints: HttpResponseMessage.Content.Headers
Console.WriteLine(fullString);
// Print the namespace
// Prints: System.Net.Http.HttpRequestMessage.Content.Headers
Console.WriteLine(FullNameOf(nameof(System.Net.Http.HttpRequestMessage.Content.Headers)));
static string StringOf(string value, [CallerArgumentExpression(nameof(value))] string fullpath = default!)
{
// Do some validation here...
string outputString = fullpath.Substring(fullpath.IndexOf("(") + 1, fullpath.IndexOf(")") - fullpath.IndexOf("(") - 1);
return outputString;
} Attribute// Example usage, do something to Car.Make.Id
[Target(nameof(Car.Make.Id)]
public static partial Car DoSomething(Car car);
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TargetAttribute : Attribute
{
public TargetAttribute(string target, [CallerArgumentExpression(nameof(target))] string fullpath = default!)
{
// Do some validation here...
// Strip "nameof(" and ")"
var strip = fullpath.Substring(fullpath.IndexOf("(") + 1, fullpath.IndexOf(")") - fullpath.IndexOf("(") - 1);
FullPath = strip;
}
// Use for reflection or source generator
public string FullPath { get; set; }
} |
Beta Was this translation helpful? Give feedback.
-
Why not reuse the current operator we already have? |
Beta Was this translation helpful? Give feedback.
-
Over seven years later and another basic language ask that is still not implemented, I'm sure the team will as usual justify it with "not enough interest" as they usually do for things that in reality they CBA to work on. Meanwhile Mapperly, and I imagine other projects, are coming up with their own implementations to cover for the lack of this simple yet important feature... I can guarantee that different projects will choose different ways of doing this and we'll end up with a fragmented ecosystem for no good reason. If you don't want to implement this feature, how 'bout you hire some people who do? It's not as if you're working for a scrappy startup that can't afford to hire developers. |
Beta Was this translation helpful? Give feedback.
-
I'm proposing making It would be great to hear in that thread about real-world use cases that support doing this, as well as real-world use cases for Spoiler: rejected! |
Beta Was this translation helpful? Give feedback.
-
Migrated from: dotnet/roslyn#14474 and dotnet/roslyn#7973
A well-know one, not much to add.
Doing this currently which is not amazing:
Beta Was this translation helpful? Give feedback.
All reactions