No Object Created To Be Dropped
ID |
csharp.no_object_created_to_be_dropped |
Severity |
high |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Code Smell |
Language |
CSharp |
Tags |
allocation, code_smell, dead-code, suspicious-statement |
Description
Reports a new T(…) that makes up an entire statement, so the object just built is assigned
to nothing, returned nowhere and passed to nobody.
Rationale
An allocation whose result goes nowhere buys nothing. Either the statement is dead code that a
reader has to puzzle over, or it is unfinished — and the most common unfinished form is a
forgotten throw. new ArgumentException("id"); compiles without a warning, so the method
keeps running with exactly the invalid input the author meant to reject, and the caller sees a
confusing failure much later.
If a constructor’s side effects really are the reason for the statement, that intent is invisible at the call site. Move the work into a named method whose signature says what happens.
A creation dropped inside a test or lifecycle method ([Fact], [Test], [SetUp], …) is not
reported: xUnit has no Assert.DoesNotThrow, so the standard idiom for asserting that a call does
not throw is to invoke it with no assertion — the test only fails if an exception propagates.
public class EntryTests
{
[Fact]
public void Ctor_ShouldNotThrow()
{
new Entry("id"); // OK — xUnit no-throw idiom, this is a test method
}
}
public class Registrar
{
public void Register(string id)
{
if (id == null)
{
new ArgumentNullException(nameof(id)); // FLAW — the exception is built, never thrown
}
new Entry(id); // FLAW — the entry is dropped on the spot
}
public Entry RegisterOk(string id)
{
if (id == null)
{
throw new ArgumentNullException(nameof(id)); // OK, the exception is thrown
}
Entry entry = new Entry(id); // OK, the instance is kept
return entry; // OK, and handed to the caller
}
}
Remediation
Decide what the object was for. If it is an exception, add the missing throw. If it is a value
the code needs, assign it, return it or pass it on. If the statement is genuinely useless, delete
it. If the constructor performs work that must happen, expose that work as a named method and
call that instead.