12

To start, I know how to reference System.Numerics to give the compiler access to the Complex type it's asking for, I just don't understand why it's necessary.

I have this basic struct:

/// <summary>
///     Describes a single point on a spectrum.
/// </summary>
public struct SpectrumPoint
{
    public SpectrumPoint(double wavelength, double intensity)
    {
        Wavelength = wavelength;
        Intensity = intensity;
    }
    public double Intensity { get; }
    public double Wavelength { get; }
}

It is used in a class that needs double[] arrays to use as arguments to third party dependency. I use this LINQy lambda chain construct them:

using Accord.Math;
// ...
double[] _wavelengths = points.Select(point => point.Wavelength).ToArray();
double[] _intensities = points.Select(point => point.Intensity).ToArray();

This is the error caused by those LINQ expressions:

Error CS0012
The type Complex is defined in an assembly that is not referenced.
You must add a reference to assembly
System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

I know this sort of error can be caused by unused method overloads that reference external assemblies, like here, but neither .Select() nor .ToArray() have any overloads that refer to Complex. What's going on?


EDIT:

This exactly replicates the compilation problem, which goes away if using Accord.Math; is removed:

using System.Linq;
using Accord.Math;

public class A
{
    public A(IEnumerable<double> d)
    {
        double[] arr = d.ToArray();
    }
}

(Here is Accord.Math.)

Community
  • 1
  • 1
kdbanman
  • 10,161
  • 10
  • 46
  • 78
  • 4
    The code you've shown doesn't refer to `Complex` *or any other type*. Can you provide a short but complete program which demonstrates the problem? It's not clear where `Accord.Math` fits in at all. – Jon Skeet Sep 03 '15 at 16:12
  • 1
    Obviously the pieces you provide alone don't cause this error, so it's hard to guess. Create a minimal example (and when you'll be at it, you'll probably identify the problem yourself ;) ). – BartoszKP Sep 03 '15 at 16:14
  • I copied your code snippet and compiled in VS2013, C# console applciation, no such error. – Matt Sep 03 '15 at 16:18
  • Thanks for the quick responses, everyone! @JonSkeet, `Accord.Math` *will* be used for interpolation. Everyone: I've included more complete context where the problem sits for now, and I'm working on the minimal project to replicate the issue! – kdbanman Sep 03 '15 at 16:26
  • Okay, I've reproduced the issue now. I have an idea what it might be... – Jon Skeet Sep 03 '15 at 16:40
  • I've reproduced as well - see the edit. – kdbanman Sep 03 '15 at 16:50
  • That's still *way* longer than required - see the code I've just added to the end of my answer ;) – Jon Skeet Sep 03 '15 at 16:53
  • I'd suggest an edit to the question title though - you're really asking *why* you need to add a reference, not *how*. – Jon Skeet Sep 03 '15 at 16:55
  • Feedback incorporated! – kdbanman Sep 03 '15 at 17:03

2 Answers2

11

I believe the problem is due to Accord.Math.ComplexMatrix - a static class with a bunch of extension methods, including:

public static double[,] ToArray(this Complex[] c);

I get the error with:

using static Accor.Math.ComplexMatrix;

... but I don't get it with a similar using static directive for other types in the same namespace.

Changing your ToArray calls to explicitly Enumerable.ToArray calls like this makes the error go away:

_wavelengths = Enumerable.ToArray(points.Select(point => point.Wavelength));
_intensities = Enumerable.ToArray(points.Select(point => point.Intensity));

... which is a further suggestion that it's ComplexMatrix.ToArray causing the problem.

Basically you don't want to use any extension methods imported. Options:

  • Call Enumerable.ToArray directly as shown above
  • Remove using Accord.Math and fully-qualify any uses of types within that namespace
  • Use a namespace alias, e.g. using AM = Accord.Math and then use that for any uses of types within the namespace, e.g. var p3 = new AM::Point3().
  • Use type aliases for any types you need within the namespace, e.g. using Point3 = Accord.Math.Point3; then you can just use var p3 = new Point3(); as normal.

Now admittedly the compiler could potentially work out that that call was infeasible regardless of how Complex is defined, as there can't possibly be a single user-defined conversion from double[] to Complex[], but spotting that would add complexity into both the language and the compiler.

Here's a really short but complete example that demonstrates it:

using System.Linq;
using Accord.Math; // Comment this out and the error goes away

class Test
{
    static void Main(string[] args)
    {
        args.ToArray();
    }
}    
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I'll use the explicit `Enumerable.ToArray` and research `using static` (which I've never seen before). That was some very fast sleuthing - thank you for the effort! – kdbanman Sep 03 '15 at 16:55
  • 1
    @kdbanman: `using static` is new in C# 6. I've added a couple more options you could consider instead of `Enumerable.ToArray` – Jon Skeet Sep 03 '15 at 18:08
3

You can take a look at the Accord.Math Project on Github as see that it references System.Numerics. You most likely have some code that uses a Accord.Math Type that references the Complex Type, so you'll need to reference the dll.

<ItemGroup> 
  <Reference Include="System" /> 
  <Reference Include="System.Data" /> 
  <Reference Include="System.Numerics" Condition="'$(Configuration)' != 'NET35'" /> 
  <Reference Include="System.Xml" /> 
</ItemGroup> 
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • 2
    I'd expect there to be a need to reference it for anything hitting System.Numerics to work at execution time, but not necessarily at *compile*-time. – Jon Skeet Sep 03 '15 at 16:28
  • Right, but now that's basically saying what the questioner already knows - the OP is asking why it's necessary when there *doesn't* appear to be any use of code using `Complex`. That's why I've asked the OP to produce an example of the failure - I suspect they'll find the cause while trying to produce a minimal example. – Jon Skeet Sep 03 '15 at 16:37