Replies: 23 comments
-
There was a similar issue at roslyn repo, dotnet/roslyn#2178. Happy to know I'm not alone:) |
Beta Was this translation helpful? Give feedback.
-
@ig-sinicyn Nice proposal! I hadn't seen that before. I like your choice of having the attribute taking a string rather than an index better, and prefixing the attribute name with Caller would make it fit in more with the other special attributes. I'll update my proposal to incorporate some of your ideas when I get time. |
Beta Was this translation helpful? Give feedback.
-
Updated the proposal. |
Beta Was this translation helpful? Give feedback.
-
I don't have much to add, but I really like this. Would be very useful indeed. |
Beta Was this translation helpful? Give feedback.
-
@jamesqo, I do like the idea, but I had a couple of questions... Are you expecting the raw code passed in for the argument be stringified?
How would this work with localization (maybe same as Also what are your thoughts on having a little helper function such as:
In the case of exceptions, most of the core types already have some support for this. For example: throw new ArgumentNullException(nameof(someParam)); will give you a message of:
In the case of the latter two, all that is missing is automatic passing of the parameter name (which, I think, is less likely to be a concern for consumers who aren't open-source). |
Beta Was this translation helpful? Give feedback.
-
We are actively using assertions through our codebase so I think I can answer to both of your questions:)
yes, raw code as is.
Copied from dotnet/roslyn#2178 ... But when there are a thousand of them there's always a chance someone will just copy assertion block without correcting the text message. In short, the content of It contains nothing more than technical details for troubleshooting and there's as many chances anyone will want to prettify it as with content of the memory dump ;) |
Beta Was this translation helpful? Give feedback.
-
Would another approach be a hybrid between That would give the same info, at roughly the same cost, with
|
Beta Was this translation helpful? Give feedback.
-
This is a very interesting proposal. I wonder if it could be used to allow logging libraries to get direct access to interpolated string data? I love C#6's interpolated strings, but most logging libraries still require a separation of log string and arguments (particularly thinking of Serilog in this instance). I'm not sure what the impact of that would necessarily be. |
Beta Was this translation helpful? Give feedback.
-
That's a good point. Hopefully that should not be an issue because:
That said, I'm willing to consider making this an opt-in feature if you're not convinced. We could introduce a new attribute such as
Yep, as @ig-sinicyn says, no loc support. It's just a dump of the expression for purely diagnostic purposes.
Automatic passing of the parameter name is pretty much the motivation for proposing this attribute. |
Beta Was this translation helpful? Give feedback.
-
Hm, I don't think this proposal would let logs access interpolated string data. It would however let them access the names of the arguments you pass in, so if you call |
Beta Was this translation helpful? Give feedback.
-
This is only true if the method that consumes the attribute has a
That may be true, but what prevents a third party from creating a function that uses the attribute. Any consumers could then be unknowingly sharing their source code (yes, not likely to happen, especially if you properly read the documentation on functions you are calling, but still).
I would hope they would, but you never know. |
Beta Was this translation helpful? Give feedback.
-
They aren't "sharing" their source code: you will have to look through the IL to see the strings. Chances are if you know how to look through IL then you also know how to use a decompiler, so there will be little new information revealed from the extra strings. |
Beta Was this translation helpful? Give feedback.
-
I think the people who want to protect their source code and so would mind if some expressions from their source code were shared are the same kind of people who use obfuscators. And if they're willing to use an obfuscator, either the obfuscator could take care of this, or they could use an analyzer that makes sure they don't call such methods unknowingly. So, I think this would make life slightly worse for those people, but it would make life better for everyone else. And that sounds like an acceptable tradeoff to me. |
Beta Was this translation helpful? Give feedback.
-
Seems like a sensible proposal, especially considering that in C++ land we already have this functionality, albeit in a quirky way (macros). In addition to debugging, I would also appreciate this approach in unit testing: instead of the never-ending |
Beta Was this translation helpful? Give feedback.
-
@gafter What do you think of this proposal? It seems like everyone so far has been in favor of it one way or another (even @tannergooding thumbed-up @svick's comment). It isn't adding any new syntax to the language, has a clear, common use case, and isn't unprecedented because the compiler already does something similar for the other |
Beta Was this translation helpful? Give feedback.
-
Just to be clear, I'm not on the language design team, so my thumbs up means very little 😄 |
Beta Was this translation helpful? Give feedback.
-
@tannergooding I meant it as you had pointed out a potential issue with the proposal, but you still were in support of it. |
Beta Was this translation helpful? Give feedback.
-
Can the |
Beta Was this translation helpful? Give feedback.
-
@jnm2 I'm not sure I understand what you are asking. Are you saying that What is the reason for that? The string is meant to be viewed by humans, who I think prefer to see expressions in their language of choice. If you want a language agnostic description of an expression, that's what expression trees are for. (That currently requires you to use a lambda, but maybe it doesn't have to, see F# auto-quotations.) |
Beta Was this translation helpful? Give feedback.
-
@svick Yes, that's what I'm asking. But further. The example was brought up of |
Beta Was this translation helpful? Give feedback.
-
@jnm2 How would you imagine that string to look? Like I said, it sounds to me like you're designing expression trees, which already do pretty much what you're asking for. |
Beta Was this translation helpful? Give feedback.
-
Yep. To be clear, the new feature doesn't entirely supplant passing in arguments directly, e.g. With xUnit |
Beta Was this translation helpful? Give feedback.
-
I think it's OK. I don't imagine it would rank very high among the other small features we're looking at. I'll have the LDM triage it. |
Beta Was this translation helpful? Give feedback.
-
Motivation
When an exception is thrown or an assert/unit test fails, it's not always obvious what went wrong just from looking at the stack trace. Part of the reason for this is that you can't see the condition that failed. If you write
Debug.Assert(array != null)
and it fails, the stack trace will only contain the filename and the line number. You will have to open up a text editor and navigate to that file to see what went wrong. It would be ideal ifDebug.Assert
actually showed you the string"array != null"
in the failure message.Proposal
Add a
CallerArgumentExpression
attribute allowing callees to 'stringify' the expressions passed in at a callsite. The constructor of the attribute will take anstring
argument specifying the name of the argument to stringify.The attribute will work the same as other
Caller*
attributes likeCallerMemberName
,CallerFilePath
, etc. The compiler will replace the optional parameter with the string of the expression of the argument having the name specified in the attribute.The compiler will verify that the name is valid at compile-time, e.g.
[CallerArgumentExpression(null)]
or[CallerArgumentExpression("cnodition")]
in this example will raise an error.The use cases for this are not limited to
Debug.Assert
. Consider the possibility of creating a helper class for argument validation without needing to usenameof
:Now we can validate parameters as follows
One could also see how this attribute could be used by test frameworks to provide better error messages when passing in a boolean, e.g. in the case of xUnit
Assert.True
orAssert.False
could be more helpful.Beta Was this translation helpful? Give feedback.
All reactions