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 typeComplex
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?
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
.)
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:
Enumerable.ToArray
directly as shown aboveusing Accord.Math
and fully-qualify any uses of types within that namespaceusing AM = Accord.Math
and then use that for any uses of types within the namespace, e.g. var p3 = new AM::Point3()
.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();
}
}
See more on this question at Stackoverflow