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

Fix S2933 FP: readonly fields in a struct re-assigned with 'this' #9657

Open
fiotti opened this issue Aug 26, 2024 · 2 comments
Open

Fix S2933 FP: readonly fields in a struct re-assigned with 'this' #9657

fiotti opened this issue Aug 26, 2024 · 2 comments
Assignees
Labels
Area: C# C# rules related issues. Type: False Positive Rule IS triggered when it shouldn't be.

Comments

@fiotti
Copy link

fiotti commented Aug 26, 2024

Description

S2933 disagrees with IDE0064.

Repro steps

struct Buffer : IDisposable
{
    byte[]? _rented; // S2933: Make '_rented' 'readonly'.
    byte[] _bytes; // S2933: Make '_bytes' 'readonly'.

    public byte[] Data => _bytes;

    public Buffer(byte[] buffer)
    {
        _bytes = buffer;
    }

    public Buffer(int capacity)
    {
        _rented = ArrayPool<byte>.Shared.Rent(capacity);
        _bytes = _rented;
    }

    public void Dispose()
    {
        if (_rented != null)
            ArrayPool<byte>.Shared.Return(_rented);

        this = default; // <-- Look here.
    }
}

But after adding the readonly modifiers, Visual Studio complains with:

IDE0064: Struct contains assignment to 'this' outside of costructor. Make readonly fields writable.

Expected behavior

I would expect SonarLint to either disable IDE0064 or not report this case at all.

According to Microsoft it is incorrect to add the readonly modifiers in this case.

Actual behavior

SonarLint reports a warning.

Known workarounds

#pragma warning disable S2933

or

#pragma warning disable IDE0064

or

 public void Dispose()
 {
     if (_rented != null)
         ArrayPool<byte>.Shared.Return(_rented);

-    this = default; // <-- Look here.
+    _rented = null;
+    _bytes = null!;
 }

Related information

  • SonarLint for Visual Studio 2022, version 8.9.0.92083
  • Visual Studio Professional 2022 (64 bit), version 17.10.4
  • dotnet 8.0.303
  • MSBuild version 17.10.4+10fbfbf2e for .NET Framework, version 17.10.4.21802
  • Windows 11 Pro 23H2 22631.3880
@fiotti fiotti changed the title Fix S2933 FP/FN: Issue title Fix S2933 FP/FN: readonly fields in a struct re-assigned with 'this' Aug 26, 2024
@fiotti fiotti changed the title Fix S2933 FP/FN: readonly fields in a struct re-assigned with 'this' Fix S2933 FP: readonly fields in a struct re-assigned with 'this' Aug 26, 2024
@SonarSource SonarSource deleted a comment Aug 26, 2024
@SonarSource SonarSource deleted a comment Aug 26, 2024
@zsolt-kolbay-sonarsource zsolt-kolbay-sonarsource added Type: False Positive Rule IS triggered when it shouldn't be. Area: C# C# rules related issues. labels Aug 26, 2024
@zsolt-kolbay-sonarsource
Copy link
Contributor

Hi @fiotti. Thank you for reporting the issue. Confirmed as False Positive.

Out of curiosity: why do you use a struct instead of a class in the code sample? Creating an IDisposable struct sounds dangerous, as it's passed by value (copied).

var buf = new Buffer();
using (var insideBuffer = new Buffer(1000))
{
   buf = insideBuffer;
}
// After this line buf._rented will point to a memory location that's no longer usable.

@fiotti
Copy link
Author

fiotti commented Aug 27, 2024

Hi @zsolt-kolbay-sonarsource 🙋‍♂️ This example is artificial just to trigger the warning. I used a struct instead of a class because it's not possible to assign this = something; inside classes.

For reference, I took inspiration from this code from Microsoft, which happens to involve a ref struct with a Dispose() method, even though it doesn't implement IDisposable as ref structs cannot implement interfaces.

Microsoft agrees with you, btw. They are not making this struct public until we get support for the [NonCopyable] attribute which allows to mark structs as non-safe-for-copy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: C# C# rules related issues. Type: False Positive Rule IS triggered when it shouldn't be.
Projects
None yet
Development

No branches or pull requests

2 participants