Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Mark applicable structs as readonly #24997

Merged
merged 2 commits into from
Nov 3, 2017

Conversation

stephentoub
Copy link
Member

@stephentoub stephentoub commented Nov 1, 2017

Fixes #24900
Related to dotnet/coreclr#14789
Related to dotnet/corert#4855

cc: @jkotas, @jaredpar, @VSadov, @tmat for System.Reflection.Metadata (which has the bulk of the changes)

@marek-safar
Copy link
Contributor

I am wondering if this is potentially a breaking change. The runtimes don't ensure that the struct is read-only but C# compiler assumes that. Therefore in a scenario where read-only struct is used in pinvoke and actually modified are we sure the side effects are always visible?

@stephentoub
Copy link
Member Author

I am wondering if this is potentially a breaking change. The runtimes don't ensure that the struct is read-only but C# compiler assumes that. Therefore in a scenario where read-only struct is used in pinvoke and actually modified are we sure the side effects are always visible?

Can you provide an example?
cc: @jaredpar, @VSadov

@marek-safar
Copy link
Contributor

I don't right now but possibly something like this where you pass in readonly version instead of non-readonly version and runtime decides to optimize/flow it differently.

readonly struct Foo
{
	public readonly int foo;
}

class X
{
	[DllImport ("foo.dll")]
	static extern void Foo (ref Foo foo);
}

@stephentoub
Copy link
Member Author

possibly something like this

@jaredpar or @VSadov could likely answer better, but from my perspective, in your example you can already do that with readonly fields (just remove the 'readonly' from the struct itself), and it's not really any different from that. Interop is inherently unsafe and allows you to break out of whatever language/runtime enforcement exists.

@stephentoub
Copy link
Member Author

@dotnet-bot test Linux x64 Release Build please (#25004)

@jkotas
Copy link
Member

jkotas commented Nov 2, 2017

Also, you can change readonly fields via reflection today. Runtime is not enforcing readonliness for reflection access either.

C# readonly is pretty similar to C++ const in this sense. There are number of ways how one can step around it.

@VladimirReshetnikov
Copy link

Making System.Nullable<T> a readonly struct would be a breaking change. Consider the following program:

using System;

struct S
{
    int x;

    public override string ToString()
    {
        x = 5;
        return "";
    }

    static void Main()
    {
        S? s = new S();
        Console.WriteLine(s.Value.x); // 0
        s.ToString();
        Console.WriteLine(s.Value.x); // 5
    }
}

If System.Nullable<T> were a readonly struct, both lines would print 0.

@stephentoub
Copy link
Member Author

Thanks for calling this out, @VladimirReshetnikov. It's not so much making Nullable<T> readonly that's the problem, but rather changing its value field to be readonly (and then the type can't be readonly). I've put up a PR to revert it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants