繁体   English   中英

为什么我不能在 C# 中实现泛型方法?

[英]Why Can't I implement generic method in C#?

我正在尝试在 c# 中实现一个简单的通用方法,该方法可以将 NI ComplexSingle和 NI ComplexDouble结构转换为System.Numerics中定义的Complex ,这也是一个结构。 ComplexSingleComplexDouble都具有此处定义的RealImaginary属性:

    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数组。 我希望通过使用如下的通用方法来做到这一点。 但是,我很快意识到无法找到RealImaginary属性,因为传入的泛型不知道它们。 然后,我想也许我可以使用一个接口,我在下面定义它具有在实际结构中找到的属性。 现在我在以下位置收到错误消息:

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 中有实部和虚部属性时才会出现错误。 我在想我不太了解接口,因为我在想既然我在接口中定义了RealComplex ,那么代码就会知道在查找泛型类型时查找它们。 不过,我想那是错误的。 我猜你可以在泛型方法中以某种方式引用对象或结构的属性,但这听起来比我希望的要复杂..?

您不能编写一个方法来转换这两种类型。 两种类型各有一个Real和一个Imaginary属性,但这些属性的类型不同。

ComplexDouble类型具有double类型的RealImaginary属性。

ComplexSingle类型具有float类型的RealImaginary属性。

最简单的解决方案是使用方法重载:您可以拥有两个名称相同但参数类型不同的方法。 然后,编译器将根据您传递给它们的参数类型自动选择正确的方法:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM