This project is read-only.

C#/VB Language Design Meeting notes - 2014-10-01

Topics: C# Language Design, VB Language Design
Oct 1, 2014 at 10:53 PM
Edited Oct 3, 2014 at 1:25 AM
There were two agenda items...
  1. Assignment to readonly autoprops in constructors (we fleshed out details)
  2. A new compiler warning to prevent outsiders from implementing your interface? (no, leave this to analyzers)

Assignment to readonly autoprops in constructors

public struct S {
   public int x {get;}
   public int y {get; set;}
   public Z z {get;}

   public S() {
      x = 15;
      y = 23;
      z.z1 = 1;
   }
}

public struct Z { int z1; }
What are the rules under which assignments to autoprops are allowed in constructors?

Absolute We can't be more permissive in what we allow with readonly autoprops than we are with readonly fields, because this would break PEVerify. (Incidentally, PEVerify doesn't check definite assignment in the constructor of a struct; that's solely a C# language thing).

Overall principle When reading/writing to an autoprop, do we go via the accessor (if there is one) or do we bypass it (if there is one) and access the underlying field directly?
Option1: language semantics say the accessor is used, and codegen uses it.
Option2: in an appropriate constructor, when there is a "final" autoprop (either non-virtual, or virtual in a sealed class), access to an autoprop means an access to the underlying field. This meaning is used for definite assignment, and for codegen. Note that it is semantically visible whether we read from an underlying field vs through an accessor, e.g. in int c { [CodeSecurity] get;}
Resolution: Option1. Under Option2, if you set a breakpoint on the getter of an autoprop, gets of it would not hit the breakpoint if they were called in the constructor which is weird. Also it would be weird that making the class sealed or the autoprop non-virtual would have this subtle change. And things like Postsharper wouldn't be able to inject. All round Option2 is weird and Option1 is clean and expected.

Definite Assignment. Within an appropriate constructor, what exactly are the rules for definite assignment? Currently if you try to read a property before all fields have been assigned then it says CS0188 'this' cannot be used before all fields are assignment, but reading a field is allowed so long as merely that field has been assigned. More precisely, within an appropriate constructor, for purposes of definite assignment analysis, when does access of the autoprop behave as if it's an access of the backing field?
Option1: never
Option2: Only in case of writes to readonly autoprops
Option3: In the case of writes to all autoprops
Option4: In the case of reads and writes to all autoprops
Resolution: Option4. This is the most helpful to developers. You might wonder what happens if it's a virtual autoprop and someone overrides getter or setter in derived types in such a way that would violate the definite assignment assumptions. But for structs there won't be derived types, and for classes the semantics say that all fields are assigned to default(.) so there's no difference.

Piecewise initialization of structs. In the code above, do we allow z.z1 = 15 to assign to the field of a readonly struct autoprop?
Option1: Yes by threating access to "z" for purposes of definite assignment as an access of the underlying field.
_Option2: _ No because in z.z1 the read of z happens via the accessor as per the principle above, and thus returns an rvalue, and hence assignment to z.z1 can't work. Instead you will have to write z = new Z(...).
Resolution: Option2. If we went with Option1, then readonly autoprops would end up being more expressive than settable autoprops which would be odd! Note that in VB you can still write _z.z1 = 15 if you do want piecewise assignment.

Virtual. What should happen if the readonly autoprop is virtual, and its getter is overridden in a derived class?
Resolution: All reads of the autoprop go via its accessor, as is already the case.

Semantic model. In the line x = 15 what should the Roslyn semantic model APIs say for the symbol x ?
Resolution: they refer to the property x. Not the backing field. (Under the hood of the compiler, during lowering, if in an appropriate constructor, for write purposes, it is implicitly transformed into a reference to the backing field). More specifically, for access to an autoprop in the constructor,
  1. It should bind to the property, but the property should be treated as a readable+writable (for purposes of what's allowed) in the case of a readonly autoprop.
  2. The definite assignment behavior should be as if directly accessing the backing field.
  3. It should code gen to the property accessor (if one exists) or a field access (if not).
Out/ref arguments in C#. Can you pass a readonly autoprop as an out/ref argument in C#?
Resolution: No. For readonly autoprops passed as ref arguments, that wouldn't obey the principle that access to the prop goes via its accessor. For passing readonly autoprops as out arguments with the hope that it writes to the underlying field, that wouldn't obey the principle that we bind to the property rather than the backing field. For writeonly autoprops, they don't exist because they're not useful.

Static readonly autoprops Should everything we've written also work for static readonly autoprops?
Resolution: Yes. Note there's currently a bug in the native compiler (fixed in Dev14) where the static constructor of a type G<T> is able to initialize static readonly fields in specializations of G e.g. G<T>.x=15;. The CLR does indeed maintain separate storage locations for each static readonly fields, soG<int>.gandG<string>.g` are different variables. (The native compiler's bug where the static constructor of G could assign to all of them resulted in unverifiable code).

VB rules in initializers as well as constructors. VB initializers are allowed to refer to other members of a class, and VB initializers are all executed during construction time. Should everything we've said about behavior in C# constructors also apply to behavior in VB initializers?
Resolution: Yes.

VB copyback for ByRef parameters. In VB, when you pass an argument to a ByRef parameter, then either it passes it as an lvalue (if the argument was a local variable or field or similar) or it uses "copy-in to a temporary then invoke the method then copy-out from the temporary" (if the argument was a property), or it uses "copy-in to a temporary then invoke the method then ignore the output" (if the argument was an rvalue or a constant). What should happen when you pass a readonly autoprop to a ByRef parameter?
Option1: Emit a compile-time error because copyback is mysterious and bites you in mysterious ways, and this new way is even more mysterious than what was there before.
Option2: Within the constructor/initializers, copy-in by reading via the accessor, and copy-back by writing to the underlying field. Elsewhere, copy-in with no copy-out. Also, just as happens with readonly fields, emit an error if assignment to a readonly autoprop happens in a lambda in a constructor (see code example below)
Resolution: Option2. Exactly has happens today for readonly fields. Note incidentally that passing a readonly autoprop to a ByRef parameter will have one behavior in the constructor and initializers (it will do the copy-back), and will silently have different behavior elsewhere (it won't do any copy-back). This too is already the case with readonly fields. On a separate note, developers would like to have feedback in some cases (not constants or COM) where copyback in a ByRef argument isn't done. But that's not a question for the language design meeting.

VB copyin for writeonly autoprops. VB tentatively has writeonly autoprops for symmetry, even though they're not useful. What should happen when you pass a writeonly autoprop as a ByRef argument?
Resolution: Yuck. This is a stupid corner case. Notionally the correct thing is to read from the backing field, and write via the setter. But if it's easier to just remove support for writeonly autoprops, then do that.
Class C
    ReadOnly x As Integer = 15

    Public Sub New()
        f(x)
        Dim lamda = Sub()
                        f(x) ' error BC36602: 'ReadOnly' variable
                        ' cannot be the target of an assignment in a lambda expression
                        ' inside a constructor.
                    End Sub
    End Sub
    Shared Sub f(ByRef x As Integer)
        x = 23
    End Sub
End Class
Oct 1, 2014 at 11:11 PM
Edited Oct 3, 2014 at 5:08 PM
We discussed a potential new error message in the compiler.

Scenario: Roslyn ships with ISymbol interface. In a future release it wants to add additional members to the interface. But this will break anyone who implemented ISymbol in its current form. Therefore it would be good to have a way to prevent anyone else from implementing ISymbol. That would allow us to add members without breaking people.

Is this scenario widespread? Presumably, but we don't have data and haven't heard asks for it. There are a number of workarounds today. Some workarounds provide solid code guarantees. Other workarounds provide "suggestions" or "encouragements" that might be enough for us to feel comfortable breaking people who took dependencies where we told them not to.

Counter-scenario: Nevertheless, I want to MOCK types. I want to construct a mock ISymbol myself maybe using MOQ, and pass it to my functions which take in an ISymbol, for testing purposes. I still want to be able to do this. (Note: MOQ will automatically update whenever we add new members to ISymbol, so users of it won't be broken).


Workarounds
  1. Ignore the problem and just break people.
  2. Like COM, solve it by adding new incremental interfaces ISymbol2 with the additional members. As Adam Speight notes below, you can make ISymbol2 inherit from ISymbol.
  3. Instead of interfaces, use abstract classes with internal constructors. Or abstract classes but never add abstract methods to it; only virtual methods.
  4. Write documentation for the interface, on MSDN or in XML Doc-Comments, that say "Internal class only; do not implement it". We see this for instance on ICorThreadpool.
  5. Declare a method on the interface which has an internal type in its signature. The CLR allows this but the language doesn't so it would have to be authored in IL. Every type which implements the interface would have to provide an implementation of that method.
  6. Write run-time checks at the public entry points of key Roslyn methods that take in an ISymbol, and throw if the object given was implemented in the wrong assembly.
  7. Write a Roslyn analyzer which is deployed by the same Nuget package that contains the definition of ISymbol, and have this analyzer warn if you're trying to implement the interface. This analyzer could be part of Roslyn, or it could be an independent third-party analyzer used by many libraries.
Proposal: Have the compiler recognize a new attribute. Given the following code
[System.Runtime.CompilerServices.InternalImplementationOnly] interface I<...> {...}
it should be a compile-time warning for a type to implement that interface, directly or indirectly, unless the class is in the same assembly as "I" or is in one of its InternalsVisibleTo friends. It will also be a compile-time error for an interface to inherit from the interface in the same way. Also, we might ask for the .NET Framework team to add this attribute in the same place as System.Runtime.CompilerServices.ExtensionAttribute, and CallerMemberNameAttribute. But doing it isn't necessary since the compiler will recognize any attribute with that exact fully-qualified name and the appropriate (empty) constructor.

Note that this rule would not be cast-iron, since it won't have CLR enforcement. It would still be possible to bypass it by writing IL by hand, or by compiling with an older compiler. But we're not looking for cast-iron. We're just looking for discouragement strong enough to allow us to add members to ISymbol in the future. (In the case of ISymbol, it's very likely that people will be using Roslyn to compile code relating to ISymbol, but that doesn't apply to other libraries).


Resolution: Workaround #7 is a better option than adding this proposal to the language.
Oct 2, 2014 at 12:42 AM
Wny cant you use inherited interfaces?
Interface ISymbolExtended inherits ISymbol
'new members
End interface
Oct 2, 2014 at 12:46 AM
AdamSpeight2008 wrote:
Why cant you use inherited interfaces?
You can! That's workaround #2. (But then every single method that takes in or returns an ISymbol would have to change to ISymbolExtended, which would be a pain). It's just a direction towards a messy type system that's caused by back-compat considerations, not by good-design considerations.
Oct 2, 2014 at 12:53 AM
Edited Oct 2, 2014 at 12:54 AM
Or you utilise that fact it inherits from ISymbol and thus an ISymbol and do type matching.
Select Type someSymbol
  Case s As ISymbolExtended
  Case s As ISymbol
End Select
Oct 2, 2014 at 3:16 AM
The System.Runtime.CompilerServices.InternalImplementationOnly attribute does be useful to enterprise code, where interfaces are often used as the API of modules. Some are inappropriate usage only because of Java influence or recommendation from some books which are not about API. But testability and mockability is the real benefit, even when it looks wrong from API point of view. Anyway, the result is that interfaces are used a lot as API only, but not intended to be implemented by consumer code, except for mocking.

So, we suffer the same interface extension issue which you mentioned. It would be very useful if we can mark the intention of the interfaces, to give a warning that we don't guarantee the compatibility of this interface.

But, I also agree that it may not help as expected. For developers who do not think in API point of view, they will not consider adding this attribute either. They will simply continue commiting no binary compatiblity and pushing the cost to API consumer side.
Oct 2, 2014 at 7:07 PM
@lwischik

Another option is to add a version number to the interface.
[version(1.0.0.0)]
interface ISymbol {  }

[version(2.0.0.0)]
interface ISymbol {  } <: ISymbol [version(1.0.0.0)]
Overloaded interfaces.

Then require the implementer to specify which version they are implementing.
class Foo implements ISymbol [version(2.0.0.0)]
{ }
Oct 2, 2014 at 9:25 PM
lwischik wrote:
There were two agenda items...
  1. Assignment to readonly autoprops in constructors (we fleshed out details)
Was any consideration given to the idea of having a concise syntax for autoproperties with explicitly-named backing fields (which could either be read-only or not, as convenient)?
  1. A new compiler warning to prevent outsiders from implementing your interface? (no, leave this to analyzers)
At what level are the rules regarding visibility of method parameters enforced? Are those only enforced in the compiler or would the class loader enforce those as well? I've long thought there should be a means by which an interface or concrete class could limit implementation or derivation to the assembly in which it resides. While it would be possible for a class to have a private interface which derives from the public-facing one, and cast to the private type all references of the interface type which are received from outside code, but that really seems rather hokey. If members whose types were not visible to outside code were themselves not visible to outside code, that would resolve the issue.
On a separate note, developers would like to have feedback in some cases (not constants or COM) where copyback in a ByRef argument isn't done. But that's not a question for the language design meeting.
When would such a question be addressed? The fact that VB.NET silently copies values passed as ByRef exists, from what I can tell, as concession toward VB6 compatibility; I would expect the majority of such usages are erroneous. IMHO, attributes should be defined for properties and method parameters such that, based upon the attributes of each the compiler could decide to either:
  1. Put the property value in a temporary, pass a reference to that, and then discard the temporary.
  2. Put the property value in a temporary, pass a reference to that, and then copy the temporary back to the property.
  3. Refuse compilation [as should happen if, e.g., anything other than a mutable variable is passed to Interlocked.CompareExchange.
It irks me that mutable structures are branded as "evil" when the fundamental problem is the inability to prevent compilers from silently transforming code which shouldn't compile into code which compiles but doesn't work.
Oct 2, 2014 at 10:39 PM
supercat wrote:
Was any consideration given to the idea of having a concise syntax for autoproperties with explicitly-named backing fields (which could either be read-only or not, as convenient)?
No! Could you flesh out that thought some more? Motivating scenarios? Honestly, if you're adding syntax to have explicit names backing fields, then it's not a far step from having explicit backing fields themselves...

VB continues to have private backing fields with a prepended underscore and they are readwrite (even for readonly autoprops) and you can use them from code even though they don't show up in intellisense. Given this, there's no great benefit in being able to come up with your own names. C# continues to have private backing fields with a name that's unutterable in user-code, and will use readonly backing fields for readonly autoprops.
At what level are the rules regarding visibility of method parameters enforced? Are those only enforced in the compiler or would the class loader enforce those as well? If members whose types were not visible to outside code were themselves not visible to outside code, that would resolve the issue.
  1. When doing meta-import, VB/C# compilers simply decline to meta-import certain private members in order to save space. I think they meta-import private types, but not private members of classes, but I can't remember the exact details.
  2. If VB/C# compilers can't resolve every single type in a member's signature (either because it's private, or because it was defined in a reference that wasn't passed /r: to the compiler) then the compiler marks the member as bad.
  3. When doing overload resolution, if one of the candidates is bad, then the compiler (as of Roslyn) declines to make any attempt at overload resolution. That's because you wouldn't want the choice of method to be changed merely by adding or removing a reference.
What you're describing seems about the same as workaround #5 (depends on the exact requirements vs meaning of "visibility" in your sentence).

I'm not sure what it would even mean for the class loader or JITer to enforce visibility...!
When would such a question be addressed? The fact that VB.NET silently copies values passed as ByRef exists, from what I can tell, as concession toward VB6 compatibility; I would expect the majority of such usages are erroneous.
That's an interesting thought. We at the LDM hadn't thought that. I guess we positively like the ability to pass properties ByRef. I think it's nice that you can have an autoprop and use it how you would a field, e.g. int.TryParse(s, MyProperty)! But from what you said, and the example attributes you gave, we shouldn't take this for granted in future design work.

When would such a question be addressed? The question was "how should developers get the feedback they want when they pass arguments to a ByRef parameter and it does one of the many mysterious VB language behaviors like copy-in, copy-out, ignore-the-copy-out ?". I think that should start life as an analyzer written by someone who's passionate about it, either on the VB team or the public.
It irks me that mutable structures are branded as "evil" when the fundamental problem is the inability to prevent compilers from silently transforming code which shouldn't compile into code which compiles but doesn't work.
The compiler can never do this alone. Swift solves it by adding a new keyword "mutable" on struct methods that mutate its structure, and enforcing both what can be done inside the method and who/when can call it.

What VB/C# cases are you thinking of with evil mutable structs? I think of these:
  • When a local variable is readonly (e.g. the loop control variable in Using) then potentially-mutating methods are defensively performed on a copy of a struct rather than on the struct itself.
  • In the implementation of the "await" operator, if your awaiter type is a struct and its OnCompleted method is mutating, then mutations may or may not be discarded depending on whether this is the first cold await or a subsequent one. Actually we initially built it to copy the struct defensively, to support mutating struct OnCompleted methods in all cases, but it had appreciable perf overhead that didn't seem justified.
Oct 3, 2014 at 1:08 AM
lwischik wrote:
No! Could you flesh out that thought some more? Motivating scenarios? Honestly, if you're adding syntax to have explicit names backing fields, then it's not a far step from having explicit backing fields themselves...
A possible scenario would be a class with a Bounds property of type Rectangle. The class may benefit from being able to access the members of Bounds directly, even though it cannot expose the ability to do so through the property. In C# the backing field name is "unpronounceable".

As for "not far from having explicit backing fields", that might not be so bad if property syntax didn't gobble up so much vertical space in VB. In most cases I think vb.net code is more compact vertically than C# code [an "if/then/else" with two statements in each branch, for example, takes 7 lines; in C# with most bracing conventions it would take at least eight if not ten] but properties are a major exception.
VB continues to have private backing fields with a prepended underscore and they are readwrite (even for readonly autoprops) and you can use them from code even though they don't show up in intellisense. Given this, there's no great benefit in being able to come up with your own names. C# continues to have private backing fields with a name that's unutterable in user-code, and will use readonly backing fields for readonly autoprops.
If it's accessible in vb, that's good, though my understanding is that such underscore names are considered a quasi-undocumented feature [am I mistaken in that]?
I'm not sure what it would even mean for the class loader or JITer to enforce visibility...!
Suppose I were to try to code:
internal class Foo { ... }
public interface Bar { void Wowzo(Foo hey); }
At present, C# would reject that because the declaration of Wowzo is exposing internal class Foo. Suppose, however, that the C# compiler were to ignore that condition and proceded to generate data for Bar in the same was as it would if Foo had been a public class. What would happen?
When would such a question be addressed? The fact that VB.NET silently copies values passed as ByRef exists, from what I can tell, as concession toward VB6 compatibility; I would expect the majority of such usages are erroneous.
That's an interesting thought. We at the LDM hadn't thought that. I guess we positively like the ability to pass properties ByRef. I think it's nice that you can have an autoprop and use it how you would a field, e.g. int.TryParse(s, MyProperty)! But from what you said, and the example attributes you gave, we shouldn't take this for granted in future design work.
One of my peeves with regard to language design is that the language designers seem to worry too much on trying to perfect rules for the contexts in which certain things should be allowed and others not, rather than letting programmers specify contexts in which certain things should be allowed and others not. For example, a lot of code would be a lot more readable if parameters of type Single could be marked with an attribute specifying "allow implicit conversion from Double, and many bugs could be caught at compile time if parameters could be marked with attributes to *disallow* certain conversions (e.g. mark the parameters toObject.ReferenceEquals` to disallow any boxing conversions).
It irks me that mutable structures are branded as "evil" when the fundamental problem is the inability to prevent compilers from silently transforming code which shouldn't compile into code which compiles but doesn't work.
The compiler can never do this alone. Swift solves it by adding a new keyword "mutable" on struct methods that mutate its structure, and enforcing both what can be done inside the method and who/when can call it.
What difficulty would there be in having the compiler reject any attempt to call a struct method which has an MutatesThis() attribute on a read-only temporary, and any attempt to call a struct method which has a MutatesThisAtomically() attribute on anything other than a genuine mutable storage location?
Oct 3, 2014 at 2:16 AM
Edited Oct 3, 2014 at 2:17 AM
supercat wrote:
If it's accessible in vb, that's good, though my understanding is that such underscore names are considered a quasi-undocumented feature [am I mistaken in that]?
They're in the spec $9.7.4 and we're never going to remove them! But not going to show them in intellisense either because they'd be confusing for most cases.
At present, C# would reject that because the declaration of Wowzo is exposing internal class Foo. Suppose, however, that the C# compiler were to ignore that condition and proceded to generate data for Bar in the same was as it would if Foo had been a public class. What would happen?
This is exactly workaround #5. It's fine from the CLR perspective. I'm not aware of any CLR enforcement of accessibility, but I haven't explored much.
One of my peeves with regard to language design is that the language designers seem to worry too much on trying to perfect rules for the contexts in which certain things should be allowed and others not, rather than letting programmers specify contexts in which certain things should be allowed and others not. For example, a lot of code would be a lot more readable if parameters of type Single could be marked with an attribute specifying "allow implicit conversion from Double, and many bugs could be caught at compile time if parameters could be marked with attributes to *disallow* certain conversions (e.g. mark the parameters toObject.ReferenceEquals` to disallow any boxing conversions).
That's a nice principle. I'm wary of how it interacts with my pet principle "avoid counter-measures". The hero is trapped in a room and a bomb is going to go off. The dialogue goes like this:

Hero: Computer, open the door
Computer: I'm sorry Dave your nemesis placed an override which doesn't let me do that
Hero: Computer, remove the override on the door-opening
Computer: I'm sorry Dave your nemesis placed an override which doesn't let me remove the override
Hero: Computer, remove the override on the override on the door-opening
Computer: Okay
Hero: Computer, remove the override on the door-opening
Computer: Okay
Hero: Computer, open the door
Computer: Okay

We have that with "warnaserror:always". But then some warnings are marked with "this can never be treated as an error".

In your case, the performance-hungry coder would want to make sure there are no implicit conversions between floating point types. Does this concern override the parameter attribute or not?
What difficulty would there be in having the compiler reject any attempt to call a struct method which has an MutatesThis() attribute on a read-only temporary, and any attempt to call a struct method which has a MutatesThisAtomically() attribute on anything other than a genuine mutable storage location?
That sounds like a better candidate for an analyzer. If it were to go into the language itself I'm sure we'd want it driven by keyword rather than attribute. And then we'd fret that the whole thing is a heavy concept overhead for something that only a small minority of people would want.
Oct 3, 2014 at 10:39 AM
lwischik wrote:
Out/ref arguments in C#. Can you pass a readonly autoprop as an out/ref argument in C#?
Resolution: No. For readonly autoprops passed as ref arguments, that wouldn't obey the principle that access to the prop goes via its accessor. For passing readonly autoprops as out arguments with the hope that it writes to the underlying field, that wouldn't obey the principle that we bind to the property rather than the backing field. For writeonly autoprops, they don't exist because they're not useful.
What about passing readonly autoprop as out parameter inside constructor body?
Oct 3, 2014 at 3:57 PM
Edited Oct 3, 2014 at 3:58 PM
lwischik wrote:
supercat wrote:
Was any consideration given to the idea of having a concise syntax for autoproperties with explicitly-named backing fields (which could either be read-only or not, as convenient)?
No! Could you flesh out that thought some more? Motivating scenarios? Honestly, if you're adding syntax to have explicit names backing fields, then it's not a far step from having explicit backing fields themselves...
Upon some further consideration, I think I realized what I'm really after. How would you like something like
Protected myBounds As Rectangle
Public ReadOnly Property Bounds As Rectangle _
  Gets myBounds Implements IReadableBounds.Bounds
Public ReadOnly Property X As Int32 Gets myBounds.X
Public ReadOnly Property Y As Int32 Gets myBounds.Y
Public Overridable ReadOnly Property NumberOfSides As Int32 Gets 4
I wasn't so much interested in "naming" the backing field as I was in having a concise syntax for the common situation where the getter is nothing more than a single expression. I would guess that 90%+ of readonly properties are nothing more than a single return statement. I would consider code like the above to be not just more compact, but also clearer than a bunch of five-line property declarations. Even in C#, I think public readonly Rectangle Bounds {get myBounds;} would be a little nicer than public readonly Rectangle Bounds {get { return myBounds;} }.
Oct 3, 2014 at 4:58 PM
lwischik wrote:
They're in the spec $9.7.4 and we're never going to remove them! But not going to show them in intellisense either because they'd be confusing for most cases.
It's good to know it's documented, though I think much of the confusion stems from the fact that there's no distinction between declaring a public property with the intention that internal code will use the backing field directly, or declaring a public property with the intention that all access will be through the property. If what code really wants is:
Dim _Bounds As Rectangle
Public ReadOnly Bounds As Rectangle Gets _Bounds
then allowing code to actually say that would seem nicer than having code simply say Public ReadOnly Bounds As Rectangle and then having code use _Bounds without having explicitly declared it. I would guess that 90% of readonly properties could fit the Gets syntax shown above, but don't think a supermajority of those would want the backing field to be private and mutable. Many would want it protected and/or internal ("Friend"), and many would want the backing field to be read-only.
At present, C# would reject that because the declaration of Wowzo is exposing internal class Foo. Suppose, however, that the C# compiler were to ignore that condition and proceded to generate data for Bar in the same was as it would if Foo had been a public class. What would happen?
This is exactly workaround #5. It's fine from the CLR perspective. I'm not aware of any CLR enforcement of accessibility, but I haven't explored much.
The link is meaningless and I don't know what you're referring to. If the CLR would simply ignore any members that were not usable from the type that was trying to use them, then I would consider a means of declaring such members as being semantically useful.
That's a nice principle. I'm wary of how it interacts with my pet principle "avoid counter-measures". The hero is trapped in a room and a bomb is going to go off. The dialogue goes like this:
I think a more common situation would be:
Dave tries to open hatch from bedroom to residential hallway. It won't open.
"Are you sure you want to open that hatch? Some hatches are dangerous."
"Yes, Hal."
Dave tries to open hatch from residential hallway into dining area. It won't open.
"Are you sure you want to open that hatch? Some hatches are dangerous."
"Yes, Hal."
Dave tries to open hatch from dining area into service corridor. It won't open.
"Are you sure you want to open that hatch? Some hatches are dangerous."
"Yes, Hal." [with increasing annoyance]
Dave tries to open hatch from service corridor into evacuated airlock. It won't open.
"Are you sure you want to open that hatch? Some hatches are dangerous."
"Yes, Hal. Just open the [bleep]ing door."
"Whatever you say, Dave."

In your case, the performance-hungry coder would want to make sure there are no implicit conversions between floating point types. Does this concern override the parameter attribute or not?
If I had my druthers, .NET would have included separate types for IEEE64 and Real; IEEE32 and ShortReal. The IEEE types would have been coercible(*) directly to or from the physically-identical Real and ShortReal but would not have supported implicit conversions in any other context, while the Real and ShortReal types would have been mutually convertible. Additionally, I would have had arithmetic operations on ShortReal yield a Real result except in scenarios where the result would be immediately assigned to a ShortReal; in that scenario, the compiler would be allowed to perform the computation as either Real or ShortReal, whichever would be faster. There are many situations where performing the computation f1 = f2+f3+f4; entirely with Single will yield somewhat less accurate results than performing the computation as Double and then rounding the result to Single; there are some where using Single will yield results that are grossly inaccurate. There are relatively few cases where computation as Double would give a worse result, and in those specific cases I would suggest that the code should use a "strict IEEE" type to force a compiler to perform all operands with Single [I believe that presently the only way to ensure that computations are actually done as single would be f1 = CSng(f2+f3)+f4;

Since .NET doesn't include distinct types, I would suggest that attributes exist which would indicate when parameters and variables should be regarded as looser or stricter types, with stricter taking precedence. Anyone who wants to convert between a "strict" type and anything with a different physical representation would be required to use a cast, whether going from Double to Single, Single to Double, Integer to Single, etc.

(*) I would consider a value to be "directly coerced" to a type when it is assigned to a variable of that type, or is passed as the kth parameter out of n to a method for which every overload that handles n parameters either has a kth parameter of that same type, or has a kth parameter of a type to which the value is niether implicitly nor explicitly convertible.
What difficulty would there be in having the compiler reject any attempt to call a struct method which has an MutatesThis() attribute on a read-only temporary, and any attempt to call a struct method which has a MutatesThisAtomically() attribute on anything other than a genuine mutable storage location?
That sounds like a better candidate for an analyzer. If it were to go into the language itself I'm sure we'd want it driven by keyword rather than attribute. And then we'd fret that the whole thing is a heavy concept overhead for something that only a small minority of people would want.
From what I understand, for purposes of multi-language interop and CLS compliance, it would need to be an attribute. That in no way implies that a language couldn't also offer a keyword which sets the attribute (I think languages should), but since any keyword will have to apply an attribute to let outside code know of the restriction, and languages will have to recognize the attribute to honor restrictions requested in outside code, I think it makes sense to first define the attribute.

As for the extent to which it would be wanted, there are quite a few places in the .NET framework where it would be appropriate, such as the instance methods on Stopwatch, and I think there are a lot of situations where it would be clearer to write:
MyStruct.ChangeSomehow();
than either
MyStruct = MyStruct.WithSomeChange();
or
TypeOfStruct.ChangeSomehow(ref MyStruct);
but programmers are effectively pressured into requiring one of the latter forms because of the lack of any means by which the former method may be written safely.
Oct 3, 2014 at 5:06 PM
Przemyslaw wrote:
lwischik wrote:
Out/ref arguments in C#. Can you pass a readonly autoprop as an out/ref argument in C#?
Resolution: No. For readonly autoprops passed as ref arguments, that wouldn't obey the principle that access to the prop goes via its accessor. For passing readonly autoprops as out arguments with the hope that it writes to the underlying field, that wouldn't obey the principle that we bind to the property rather than the backing field. For writeonly autoprops, they don't exist because they're not useful.
What about passing readonly autoprop as out parameter inside constructor body?
That was the answer "no". Our principle is that for language purposes when you write the syntax foo(out x), the symbol x binds to the property regardless of whether it's an autoproperty in the constructor or not. This binding applies to the rule "only lvalues are allowed for out arguments", which generates an error. The fact that x ends up being written to via its backing field is much lower level.

Our way of thinking was more like "for purposes of definite assignment, autoprops behave like fields; but for all other purposes, readonly autoprops behave as if they had an imaginary 'getter' for the duration of the constructor."
Oct 3, 2014 at 5:28 PM
Przemyslaw wrote:
What about passing readonly autoprop as out parameter inside constructor body?
An out parameter is really a ref parameter in disguise, except that the compiler is willing to ignore the fact that a variable passed as an out parameter is uninitialized. Interestingly, even when passing a variable as an out parameter to virtual method, the C# compiler does nothing to prevent an implementation written in another language from reading the previous contents of that variable (such as either clearing the variable before making the call, or creating a blank temporary variable and passing a ref to that). Passing the backing field of a class as an out parameter would allow outside code to read its value without using the property getter.
Oct 3, 2014 at 5:38 PM
supercat wrote:
Przemyslaw wrote:
What about passing readonly autoprop as out parameter inside constructor body?
An out parameter is really a ref parameter in disguise, except that the compiler is willing to ignore the fact that a variable passed as an out parameter is uninitialized. Interestingly, even when passing a variable as an out parameter to virtual method, the C# compiler does nothing to prevent an implementation written in another language from reading the previous contents of that variable (such as either clearing the variable before making the call, or creating a blank temporary variable and passing a ref to that). Passing the backing field of a class as an out parameter would allow outside code to read its value without using the property getter.
That's not the problem. C# fully permits passing a readonly field to an out parameter to a method call from within the constructor. It also allows passing a readonly field to a ref parameter as even without some form of initializer they are implicitly zeroed out. The situation here is more of semantics, the desire for read-only auto-properties to feel like they have a getter even though they don't.

Perfectly legal C# 1.0-6.0
public class Foo {
    private readonly int x;

    public Foo(string s) {
        int.TryParse(s, out x);
    }
}
Apparently not legal in C# 6.0:
public class Foo {
    private int X { get; }

    public Foo(string s) {
        int.TryParse(s, out X);
    }
}
Workaround:
public class Foo {
    private int X { get; }

    public Foo(string s) {
        int x;
        int.TryParse(s, out x);
        X = x;
    }
}
Oct 4, 2014 at 3:31 PM
Lucian,

Will the ISymbol interface be marked with an attribute, and the analyzer look for that attribute? Or hard code to ISymbol? Or something else.

As has been pointed out here, this isn't just a problem for you, but a problem we can have/are already having.

I think this analyzer can probably be created in a generalized way which would have the enormous benefit of a single attribute.

I'm not very worried about implementations. For both this (and protectedAndInternal (IL name)) I'm very, very, very, very, very worried about variations in the definition - the semantics.

If you can help us get a SINGLE attribute for key concepts like these as they come up, that will be enormously helpful.

Perhaps it is logical to have a second tier of "language suggestions" driven by the community finding common semantics that can drive adoption of non-MS analyzers and MS analyzers, spread the load for analyzers better.

I'm good, even excited about the community solving problems. But we need common semantics - a single name for the "don't re-implement this interface, that'snot what it's for" message.

Kathleen
Oct 4, 2014 at 3:45 PM
What about each aspect of ISymbol being split out into separate interfaces then use Constraint Generics on the method.
interface IValue< Vt > { .Value : Vt }
interface   IKey< Kt > { .Key   : Kt }

someMethod< T : { IKey<Int32>, IValue<String> }>
Oct 4, 2014 at 5:31 PM
KathleenDollard wrote:
Will the ISymbol interface be marked with an attribute, and the analyzer look for that attribute? Or hard code to ISymbol? Or something else.
The approach I'm aiming for would be a new platform attribute
namespace System.Runtime.CompilerServices
{
    /// <summary>
    /// This attribute is applied to an interface to require that it may only be implemented inside
    /// its own assembly, or inside assemblies to which InternalsVisibleTo access has been granted.
    /// </summary>
    public class InternalImplementationOnlyAttribute : Attribute { }
}
And an analyzer that comes with the platform that "enforces" this attribute with a diagnostic.
Oct 6, 2014 at 5:01 PM
nmgafter.

<Happy Dance>

Kathleen
Oct 6, 2014 at 11:02 PM
nmgafter wrote:
The approach I'm aiming for would be a new platform attribute
public class InternalImplementationOnlyAttribute : Attribute { }
From what I understand, if the C# or VB.NET compiler would allow a interface to contain a method with a parameter of an internal type, the resulting interface would behave to the outside world as though that method didn't exist, but any type which couldn't see the definition of that parameter's type would be unable to implement that member, and thus unable to implement the interface as a whole.
Oct 19, 2014 at 7:56 AM
supercat wrote:
An out parameter is really a ref parameter in disguise, except that the compiler is willing to ignore the fact that a variable passed as an out parameter is uninitialized. Interestingly, even when passing a variable as an out parameter to virtual method, the C# compiler does nothing to prevent an implementation written in another language from reading the previous contents of that variable (such as either clearing the variable before making the call, or creating a blank temporary variable and passing a ref to that). Passing the backing field of a class as an out parameter would allow outside code to read its value without using the property getter.
The interop parts of "Out" weighed heavily on our minds. We came up with a design for Out parameters that we thought was good:
https://roslyn.codeplex.com/discussions/540509 section 42

Unfortunately this was one of the things that didn't meet the bar for VS14.