Skip to content

Fix CS0266 in GetUnitInfo<TQuantity,TUnit> typed overload#1677

Merged
angularsen merged 1 commit into
masterfrom
claude/fix-pr1657-build-error
Jun 11, 2026
Merged

Fix CS0266 in GetUnitInfo<TQuantity,TUnit> typed overload#1677
angularsen merged 1 commit into
masterfrom
claude/fix-pr1657-build-error

Conversation

@angularsen

Copy link
Copy Markdown
Owner

Summary

Fixes the Azure Pipelines build failure introduced by #1657:

```
error CS0266: Cannot implicitly convert type 'UnitsNet.UnitInfo' to
'UnitsNet.UnitInfo<TQuantity, TUnit>'
```

at UnitsNet/Extensions/QuantityExtensions.cs:47:

```csharp
return quantity.QuantityInfo[quantity.Unit];
```

Why this happens

The receiver is statically IQuantity<TQuantity, TUnit>, whose QuantityInfo getter is shadowed (new) to return the more specific QuantityInfo<TQuantity, TUnit>. On the hosted Azure Pipelines image's Roslyn build, member lookup resolves to the inherited IQuantity<TUnit>.QuantityInfo (QuantityInfo<TUnit>) instead, so the indexer returns UnitInfo<TUnit> and the conversion to UnitInfo<TQuantity, TUnit> fails. Local builds on newer SDKs happened to resolve the shadowed member and compiled cleanly, which is why #1657's CI never tripped on the maintainer's machine.

Fix

The runtime value is always the more derived type, so cast through QuantityInfo<TQuantity, TUnit> explicitly to surface the typed indexer. No behavior change.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96%. Comparing base (700617d) to head (a959971).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@          Coverage Diff           @@
##           master   #1677   +/-   ##
======================================
  Coverage      96%     96%           
======================================
  Files         450     450           
  Lines       29177   29178    +1     
======================================
+ Hits        28136   28137    +1     
  Misses       1041    1041           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The Azure Pipelines build of #1657 (master) fails with:

  error CS0266: Cannot implicitly convert type 'UnitInfo<TUnit>' to
    'UnitInfo<TQuantity, TUnit>'

at:

  return quantity.QuantityInfo[quantity.Unit];

The receiver is statically IQuantity<TQuantity, TUnit>, whose
QuantityInfo getter is shadowed (`new`) to return the more specific
QuantityInfo<TQuantity, TUnit>. Roslyn's member lookup on hosted
images resolves the inherited IQuantity<TUnit>.QuantityInfo
(QuantityInfo<TUnit>) instead, so the indexer returns UnitInfo<TUnit>
and the conversion to UnitInfo<TQuantity, TUnit> fails.

The runtime value is always the more derived type, so cast through
QuantityInfo<TQuantity, TUnit> explicitly to surface the typed
indexer. No behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@angularsen angularsen force-pushed the claude/fix-pr1657-build-error branch from cc579d7 to a959971 Compare June 11, 2026 15:45
@claude

claude Bot commented Jun 11, 2026

Copy link
Copy Markdown

PR Review: Fix CS0266 in GetUnitInfo<TQuantity,TUnit>

This is a clean, targeted fix. A few observations:

Correctness

The cast is safe. TQuantity : IQuantity<TQuantity, TUnit> guarantees the runtime object's QuantityInfo property returns QuantityInfo<TQuantity, TUnit>, so the explicit cast won't throw. The PR description explains this well.

Minor suggestion: cast the receiver instead of the result

The ambiguity is in which QuantityInfo getter Roslyn picks. An alternative that makes the intent clearer — and avoids a cast that could theoretically fail — is to pin the dispatch site by casting the receiver:

#else
        return ((IQuantity<TQuantity, TUnit>)quantity).QuantityInfo[quantity.Unit];
#endif

quantity already satisfies IQuantity<TQuantity, TUnit> (it's the constraint), so this cast is always valid. It signals "resolve the member from this specific interface" rather than "trust that the result is the derived type."

Both approaches compile and behave identically at runtime; this is a style preference. The current approach is fine if you prefer to keep the intermediate variable for readability.

Comment wording

// This is likely a .NET SDK version compatibility thing, did not bother looking closer at it.

"Did not bother looking closer at it" is a little casual for a permanent code comment. The PR description's explanation is actually quite good — consider condensing it into the comment, e.g.:

// Older Roslyn resolves quantity.QuantityInfo to IQuantity<TUnit>.QuantityInfo (returning QuantityInfo<TUnit>)
// instead of the shadowed IQuantity<TQuantity,TUnit>.QuantityInfo. Explicit cast forces the correct overload.

No breaking changes, no behavior change

This is purely a compilation workaround for a .NET SDK version difference in member lookup. No API surface is affected. ✓

Summary

Fix is correct and the approach is valid. The two nits above (cast site and comment wording) are low-priority — happy to approve either way.

@angularsen angularsen merged commit e78bb77 into master Jun 11, 2026
2 of 3 checks passed
@angularsen angularsen deleted the claude/fix-pr1657-build-error branch June 11, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant