error CS0104: 'BarcodeReader<>' is an ambiguous reference between 'ZXing.ImageSharp.BarcodeReader<TPixel>'
and 'ZXing.BarcodeReader<T>' — two packages, two generic classes with the same name, both imported.
ZXing.Net ships ZXing.BarcodeReader<T>, a generic reader you feed with your own image-to-luminance
function. The ImageSharp binding ships ZXing.ImageSharp.BarcodeReader<TPixel>, a subclass that
already knows how to read an ImageSharp Image<TPixel>. With using ZXing; and
using ZXing.ImageSharp; both present, the compiler cannot choose. Fully qualify the ImageSharp one —
that is the one you want for decoding a PNG — and keep using ZXing; for BarcodeFormat.
The error
With ZXing.Net 0.16.11 and ZXing.Net.Bindings.ImageSharp.V3 0.16.20, the packages the test project uses:
error CS0104: 'BarcodeReader<>' is an ambiguous reference between
'ZXing.ImageSharp.BarcodeReader<TPixel>' and 'ZXing.BarcodeReader<T>'
Why it happens
C# does not import nested namespaces: using ZXing; brings in ZXing.BarcodeReader<T>
but not anything under ZXing.ImageSharp. So the core package alone never causes this. The trouble
starts when you add the second using to reach the binding's reader — now two generic types named
BarcodeReader with one type parameter are visible, and the name BarcodeReader<Rgba32>
fits both.
The AI added both usings because both namespaces contain things it needed. That is reasonable; it just did not know the two packages share a class name, and the compiler did.
The fix
// tests/ClinicLive.Tests/TicketQrTests.cs
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using ZXing; // BarcodeFormat lives here; no 'using ZXing.ImageSharp;'
var png = TicketQr.Png("PWPAP2");
using var image = Image.Load<Rgba32>(png);
// Fully qualified: ZXing and ZXing.ImageSharp both define a BarcodeReader<T>.
var reader = new ZXing.ImageSharp.BarcodeReader<Rgba32> { Options = { PossibleFormats = [BarcodeFormat.QR_CODE] } };
var result = reader.Decode(image);
Assert.Equal("cliniclive://visit/PWPAP2", result.Text);
If the type appears more than once, a using alias reads better than repeating the namespace:
using QrReader = ZXing.ImageSharp.BarcodeReader<SixLabors.ImageSharp.PixelFormats.Rgba32>;
/* ... */
var reader = new QrReader { Options = { PossibleFormats = [BarcodeFormat.QR_CODE] } };
Which reader do you want? For a decoded file in a test or on a server, the ImageSharp one: it is managed code only, so it runs on a Linux CI runner with no camera and no native libraries.
Where it bit us
Season three, Part 8 (tag pocket-08 in
the repo). The emulator could not show a QR code to its
own camera, so TicketQrTests.cs became the proof instead: the server draws the PNG, ZXing reads it back
to cliniclive://visit/PWPAP2, the shared parser pulls the code out. The ambiguity was the first thing
the compiler said about that test. The lesson: when two packages come from the same family, expect them to reuse
names, and qualify on sight.
Frequently asked
- Which ZXing BarcodeReader should I use to decode a PNG in a test?
- Use ZXing.ImageSharp.BarcodeReader with the pixel type of your loaded image, for example Rgba32. It comes from the ZXing.Net.Bindings.ImageSharp.V3 package, is managed code only, and decodes an ImageSharp Image directly, so it runs on a Linux CI runner without a camera.
- Why does using ZXing; alone not cause the ambiguity?
- C# using directives do not import nested namespaces. using ZXing; makes ZXing.BarcodeReader visible but not ZXing.ImageSharp.BarcodeReader. The error only appears once you also add using ZXing.ImageSharp;, at which point both generic readers match the simple name.
- Can I use ZXing.Net.Maui in a test project instead?
- Not for decoding a file. ZXing.Net.Maui provides a camera view control for MAUI apps and depends on platform APIs. For decoding an image in a test or on a server, use ZXing.Net plus an image binding such as the ImageSharp one.
More decoded errors in the Fixes category; the scanner this came from starts at From Prompt to Pocket, Part 1.