Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CS8852: Init-only property cannot be assigned to in an 'init' accessor if accessing it requires a cast (e.g. an explicitly implemented interface type) #50053

Closed
ericwj opened this issue Dec 18, 2020 · 7 comments · Fixed by #50424
Assignees
Labels
4 - In Review A fix for the issue is submitted for review. Area-Compilers Bug
Milestone

Comments

@ericwj
Copy link

ericwj commented Dec 18, 2020

Version Used:
Using "Csc" task from assembly "C:\Program Files\dotnet\sdk\5.0.200-preview.20601.7\Roslyn\Microsoft.Build.Tasks.CodeAnalysis.dll".

Steps to Reproduce:

Try to compile this.

public interface ISomething { int Property { get; init; } }
public record BaseType : ISomething { int ISomething.Property { get; init; } }
public record DerivedType : BaseType {
    public int SomethingElse {
        get => ((ISomething)this).Property;
        init => ((ISomething)this).Property = value;
    }
}

Expected Behavior:
Compiles.

Actual Behavior:
error CS8852: Init-only property or indexer 'ISomething.Property' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Dec 18, 2020
@DataRostiashvili
Copy link

Same problem bugs me out. Is it intentional? if so why?

@jaredpar jaredpar added Bug and removed untriaged Issues and PRs which have not yet been triaged by a lead labels Jan 8, 2021
@jaredpar jaredpar added this to the 16.9 milestone Jan 8, 2021
@jaredpar
Copy link
Member

jaredpar commented Jan 8, 2021

In the cases the cast is an identity preserving conversion on this the cast should be allowed here.

@jcouv jcouv added the 4 - In Review A fix for the issue is submitted for review. label Jan 27, 2021
@jcouv jcouv closed this as completed Jan 30, 2021
@jcouv
Copy link
Member

jcouv commented Jan 30, 2021

LDM confirmed that this is by-design. If a base type needs to expose something to initialize, it should expose APIs to do so.

@ericwj
Copy link
Author

ericwj commented Jan 31, 2021

What API? Can't do this through an interface since that introduces public API to circumvent the init-only-ness. Awkward.

@jcouv
Copy link
Member

jcouv commented Feb 1, 2021

Simply using a public interface implementation would do it:

public interface ISomething { int Property { get; init; } }
public record BaseType : ISomething { int Property { get; init; } }

Note there is a similar problem that's already existing with a private implementation with set or init property:

public record BaseType : ISomething { int ISomething.Property { get; set; } }

new BaseType() { ... can't set property ... }

@ViIvanov
Copy link

ViIvanov commented Feb 2, 2021

What API? Can't do this through an interface since that introduces public API to circumvent the init-only-ness. Awkward.

I think it could be something like this:

public interface ISomething {
  int Property { get; init; }
}

public record BaseType : ISomething
{
  protected int SomethingProperty { get; init; }
  
  int ISomething.Property {
    get => SomethingProperty;
    init => SomethingProperty = value;
  }
}

public record DerivedType : BaseType
{
  public int SomethingElse {
    get => SomethingProperty;
    init => SomethingProperty = value;
  }
}

@ericwj
Copy link
Author

ericwj commented Feb 22, 2021

I find at the very least the error message very confusing. It is also very weird to me that this works, but not the original code in the issue, with the only difference being that I don't want Property to be visible without the cast to ISomething:

public interface ISomething { int Property { get; init; } }
public record BaseType : ISomething { public int Property { get; init; } }
public record DerivedType : BaseType {
    public int SomethingElse {
        get => Property;
        init => Property = value;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4 - In Review A fix for the issue is submitted for review. Area-Compilers Bug
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

6 participants