[英]Why Can't I implement generic method in C#?
我正在尝试在 c# 中实现一个简单的通用方法,该方法可以将 NI ComplexSingle
和 NI ComplexDouble
结构转换为System.Numerics
中定义的Complex
,这也是一个结构。 ComplexSingle
和ComplexDouble
都具有此处定义的Real
和Imaginary
属性:
public double Real
{
get
{
return _privateBackingFieldForProperty_Real;
}
set
{
double privateBackingFieldForProperty_Real = _privateBackingFieldForProperty_Real;
_privateBackingFieldForProperty_Real = value;
}
}
public double Imaginary
{
get
{
return _privateBackingFieldForProperty_Imaginary;
}
set
{
double privateBackingFieldForProperty_Imaginary = _privateBackingFieldForProperty_Imaginary;
_privateBackingFieldForProperty_Imaginary = value;
}
}
我想要做的就是制作一个 function,它可以接受ComplexSingle
数组或ComplexDouble
数组,并将其中一个转换为Complex
数组。 我希望通过使用如下的通用方法来做到这一点。 但是,我很快意识到无法找到Real
和Imaginary
属性,因为传入的泛型不知道它们。 然后,我想也许我可以使用一个接口,我在下面定义它具有在实际结构中找到的属性。 现在我在以下位置收到错误消息:
Complex[] complexes = ComplexNItoComplex<ComplexDouble>(cd);
那
代码如下:
using NationalInstruments;
using System;
using System.Numerics;
namespace ComplexStuff
{
class ComplexMod
{
static void Main(string[] args)
{
Complex c1 = new Complex(4, 3);
Complex c2 = new Complex(5, 4);
Complex c3 = new Complex(6, 5);
ComplexDouble cd1 = new ComplexDouble(4, 3);
ComplexDouble cd2 = new ComplexDouble(4, 3);
ComplexDouble cd3 = new ComplexDouble(4, 3);
ComplexSingle cs1 = new ComplexSingle(7, 2);
ComplexSingle cs2 = new ComplexSingle(7, 2);
ComplexSingle cs3 = new ComplexSingle(7, 2);
ComplexDouble[] cd = new ComplexDouble[]{
cd1, cd2, cd3
};
Complex[] complexes = ComplexNItoComplex<ComplexDouble>(cd);
}
public interface IComplexNI
{
public double Real { get; set; }
public double Imaginary { get; set; }
}
static Complex[] ComplexNItoComplex<T>(IList<T> NIComplex) where T : IComplexNI
{
Complex[] c = new Complex[NIComplex.Count];
for (int i = 0; i < NIComplex.Count; i++)
{
c[i] = new Complex(NIComplex[i].Real, NIComplex[i].Imaginary);
}
return c;
}
}
}
复双:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Serialization;
using System.Security;
using NationalInstruments.Internal;
using NationalInstruments.Restricted;
namespace NationalInstruments
{
[Serializable]
[DebuggerDisplay("\\{{Real} + {Imaginary}i}")]
[TypeConverter(typeof(ComplexDoubleConverter))]
public struct ComplexDouble : IFormattable, ISerializable, IEquatable<ComplexDouble>
{
private const string RealKey = "Real";
private const string ImaginaryKey = "Imaginary";
private double _privateBackingFieldForProperty_Real;
private double _privateBackingFieldForProperty_Imaginary;
public double Magnitude => Math.Sqrt(Real * Real + Imaginary * Imaginary);
public double Phase => Math.Atan2(Imaginary, Real);
public static ComplexDouble Zero => new ComplexDouble(0.0, 0.0);
public ComplexDouble ComplexConjugate => new ComplexDouble(Real, 0.0 - Imaginary);
public double Real
{
get
{
return _privateBackingFieldForProperty_Real;
}
set
{
double privateBackingFieldForProperty_Real = _privateBackingFieldForProperty_Real;
_privateBackingFieldForProperty_Real = value;
}
}
public double Imaginary
{
get
{
return _privateBackingFieldForProperty_Imaginary;
}
set
{
double privateBackingFieldForProperty_Imaginary = _privateBackingFieldForProperty_Imaginary;
_privateBackingFieldForProperty_Imaginary = value;
}
}
public ComplexDouble(double real, double imaginary)
{
this = default(ComplexDouble);
Real = real;
Imaginary = imaginary;
}
public static ComplexDouble FromPolar(double magnitude, double phase)
{
return new ComplexDouble(magnitude * Math.Cos(phase), magnitude * Math.Sin(phase));
}
public static ComplexDouble FromDouble(double real)
{
return new ComplexDouble(real, 0.0);
}
public static explicit operator ComplexDouble(double real)
{
return FromDouble(real);
}
public override string ToString()
{
return ToString(null, null);
}
public string ToString(string format)
{
return ToString(format, null);
}
public string ToString(IFormatProvider formatProvider)
{
return ToString(null, formatProvider);
}
public string ToString(string format, IFormatProvider formatProvider)
{
string text = Real.ToString(format, formatProvider);
string text2 = Math.Abs(Imaginary).ToString(format, formatProvider);
NumberFormatInfo numberFormat = ComplexParser.GetNumberFormat(formatProvider);
string text3 = (Real.IsNegativeZero() ? numberFormat.NegativeSign : null);
string text4 = ((Imaginary < 0.0 || Imaginary.IsNegativeZero()) ? numberFormat.NegativeSign : numberFormat.PositiveSign);
return string.Format(CultureInfo.InvariantCulture, "{0}{1} {2} {3}i", text3, text, text4, text2);
}
public static ComplexDouble Parse(string input)
{
return Parse(input, null);
}
public static ComplexDouble Parse(string input, IFormatProvider provider)
{
if (input == null)
{
throw ExceptionBuilderBase.ArgumentNull("input");
}
if (!ComplexParser.AttemptParse(input, NumberStyles.Float | NumberStyles.AllowThousands, provider, ComplexParser.TryParseDouble, out var real, out var imaginary))
{
throw ExceptionBuilder.InvalidComplexDoubleFormat(input);
}
return new ComplexDouble(real, imaginary);
}
public static bool TryParse(string input, out ComplexDouble result)
{
return TryParse(input, null, out result);
}
public static bool TryParse(string input, IFormatProvider provider, out ComplexDouble result)
{
double real;
double imaginary;
bool result2 = ComplexParser.AttemptParse(input, NumberStyles.Float | NumberStyles.AllowThousands, provider, ComplexParser.TryParseDouble, out real, out imaginary);
result = new ComplexDouble(real, imaginary);
return result2;
}
public static ComplexDouble[] ComposeArray(double[] realData, double[] imaginaryData)
{
if (realData == null)
{
throw ExceptionBuilderBase.ArgumentNull("realData");
}
if (imaginaryData == null)
{
throw ExceptionBuilderBase.ArgumentNull("imaginaryData");
}
int num = realData.Length;
if (num != imaginaryData.Length)
{
throw ExceptionBuilder.ArrayLengthsNotEqual("imaginaryData");
}
ComplexDouble[] array = new ComplexDouble[num];
for (int i = 0; i < num; i++)
{
array[i] = new ComplexDouble(realData[i], imaginaryData[i]);
}
return array;
}
public static ComplexDouble[] ComposeArray(double[] realData, double[] imaginaryData, int startIndex, int length)
{
if (realData == null)
{
throw ExceptionBuilderBase.ArgumentNull("realData");
}
if (imaginaryData == null)
{
throw ExceptionBuilderBase.ArgumentNull("imaginaryData");
}
int num = realData.Length;
if (num != imaginaryData.Length)
{
throw ExceptionBuilder.ArrayLengthsNotEqual("imaginaryData");
}
if (startIndex < realData.GetLowerBound(0) || startIndex >= num)
{
throw ExceptionBuilderBase.ArgumentOutOfRange("startIndex");
}
if (length < 0 || startIndex + length > num)
{
throw ExceptionBuilderBase.ArgumentOutOfRange("length");
}
ComplexDouble[] array = new ComplexDouble[length];
int num2 = startIndex;
int num3 = 0;
while (num2 < startIndex + length)
{
array[num3] = new ComplexDouble(realData[num2], imaginaryData[num2]);
num2++;
num3++;
}
return array;
}
public static ComplexDouble[] ComposeArrayPolar(double[] magnitudes, double[] phases)
{
if (magnitudes == null)
{
throw ExceptionBuilderBase.ArgumentNull("magnitudes");
}
if (phases == null)
{
throw ExceptionBuilderBase.ArgumentNull("phases");
}
int num = magnitudes.Length;
if (num != phases.Length)
{
throw ExceptionBuilder.ArrayLengthsNotEqual("phases");
}
ComplexDouble[] array = new ComplexDouble[num];
for (int i = 0; i < num; i++)
{
array[i] = FromPolar(magnitudes[i], phases[i]);
}
return array;
}
public static ComplexDouble[] ComposeArrayPolar(double[] magnitudes, double[] phases, int startIndex, int length)
{
if (magnitudes == null)
{
throw ExceptionBuilderBase.ArgumentNull("magnitudes");
}
if (phases == null)
{
throw ExceptionBuilderBase.ArgumentNull("phases");
}
int num = magnitudes.Length;
if (num != phases.Length)
{
throw ExceptionBuilder.ArrayLengthsNotEqual("phases");
}
if (startIndex < magnitudes.GetLowerBound(0) || startIndex >= num)
{
throw ExceptionBuilderBase.ArgumentOutOfRange("startIndex");
}
if (length < 0 || startIndex + length > num)
{
throw ExceptionBuilderBase.ArgumentOutOfRange("length");
}
}
}
我知道只有在 IComplexNI 中有实部和虚部属性时才会出现错误。 我在想我不太了解接口,因为我在想既然我在接口中定义了Real
和Complex
,那么代码就会知道在查找泛型类型时查找它们。 不过,我想那是错误的。 我猜你可以在泛型方法中以某种方式引用对象或结构的属性,但这听起来比我希望的要复杂..?
您不能编写一个方法来转换这两种类型。 两种类型各有一个Real
和一个Imaginary
属性,但这些属性的类型不同。
ComplexDouble
类型具有double
类型的Real
和Imaginary
属性。
ComplexSingle
类型具有float
类型的Real
和Imaginary
属性。
最简单的解决方案是使用方法重载:您可以拥有两个名称相同但参数类型不同的方法。 然后,编译器将根据您传递给它们的参数类型自动选择正确的方法:
static Complex[] ComplexNItoComplex(IEnumerable<ComplexDouble> NIComplex)
{
return (from c in NIComplex
select new Complex(c.Real, c.Imaginary))
.ToArray();
}
static Complex[] ComplexNItoComplex(IEnumerable<ComplexSingle> NIComplex)
{
return (from c in NIComplex
select new Complex(c.Real, c.Imaginary))
.ToArray();
}
示例用法:
ComplexDouble cd1 = new ComplexDouble(4, 3);
ComplexDouble cd2 = new ComplexDouble(4, 3);
ComplexDouble cd3 = new ComplexDouble(4, 3);
ComplexSingle cs1 = new ComplexSingle(7, 2);
ComplexSingle cs2 = new ComplexSingle(7, 2);
ComplexSingle cs3 = new ComplexSingle(7, 2);
ComplexDouble[] cd = new ComplexDouble[]{
cd1, cd2, cd3
};
ComplexSingle[] cs = new ComplexSingle[]{
cs1, cs2, cs3
};
Complex[] complexes1 = ComplexNItoComplex(cd);
Complex[] complexes2 = ComplexNItoComplex(cs);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.