创建通用数据类型方法

时间:2014-08-12 18:20:30

标签: c# generics

我有一个C#应用程序,它有两种方法:

private void build_float_string() {

    float[] mData = new float[1000];
    Marshal.Copy(myPointer, mData, 0, 1000);
    mData.ToList().ForEach(i => descriptor_string.Append(string.Format("{0}, ", i.ToString())));

}

结果是字符串1.0, 1.1, 1.2, 1.3, ...。和

private void build_byte_string() {

    byte[] mData = new byte[1000];
    Marshal.Copy(myPointer, mData, 0, 1000);
    mData.ToList().ForEach(i => descriptor_string.Append(string.Format("{0}, ", i.ToString())));

}

结果是字符串1, 2, 3, 4, ...

或者无论数据是什么。

我的问题是:由于这些方法是相同的 - 除floatbyte数据类型外,我可以为此创建通用模板方法吗?我确定C++可以做到这一点,但我不知道从C#开始这样做的目的。

4 个答案:

答案 0 :(得分:1)

如果您不希望编译时类型安全,还有动态关键字(假设您使用的是c#4.0或更高版本)

private void build_string<T>() where T : struct
{
    try
    {
        T[] mData = new T[1000];
        Marshal.Copy(myPointer,(dynamic) mData, 0, 1000);
        descriptor_string.Append(String.Join(", ", mData.Select(item=>item.ToString()));
    } 
    catch(RuntimeBinderException rbe)
    {
        // Handle case here where there is no suitable Marshal.Copy Method.
    }
}

答案 1 :(得分:0)

您可以使用Type类或Ty​​pe参数,我希望这会有所帮助:

class Program
{
    static void Main(string[] args)
    {
        DateTime dtNow = DateTime.Now;
        Console.WriteLine("String of float: " + getTheString<float>(12.7f));
        Console.WriteLine("String of DateTime: " + getTheString<DateTime>(dtNow));

        Console.WriteLine("The type name for a float number: " + getTheTypeName(18.25f));
        Console.WriteLine("The type name for a DateTime object: " + getTheTypeName(dtNow));

        Console.WriteLine("the result of making an instance for a float type: " + 
            makeOneInstanceOfType(20.2f, typeof(float)));
        Console.WriteLine("the result of making an instance for a DateTime type: " +
            makeOneInstanceOfType(0, typeof(DateTime)));

        //Using GetType() instead of typeof(..)
        Console.WriteLine("the result of making an instance for a DateTime type: " +
                      makeOneInstanceOfType(0, typeof(DateTime)));

        Console.ReadLine();
    }

    //Using the Type Parameter (T) for creating instances of T which T is your type,
    //specified when calling the method
    private static string getTheString<T>(T arg)
    {
        return arg+"";
    }

    //Using Type by calling the GetType() method of the object
    private static string getTheTypeName(object arg)
    {
        return arg.GetType().FullName;
    }

    //Direct use of Type, creates a float and fills is with the value if theType is float,
    //otherwise makes an instance of theType.
    private static object makeOneInstanceOfType(float valIfFloat, Type theType)
    {
        object instance;
        if(theType.IsEquivalentTo(typeof(float)))
        {                
            instance = valIfFloat;
        }
        else
        {
            instance = Activator.CreateInstance(theType);
        }
        return instance;
    }
}

答案 2 :(得分:0)

我认为你不能,因为Marshal.Copy()

没有通用的重载

然而,您可以将第二部分设为通用部分:

    static StringBuilder BuildString<T>(IEnumerable<T> array, StringBuilder sb)
    {
        return array.Aggregate(sb, (s, f) => s.Append(string.Format("{0}, ", f.ToString())));
    }

    static StringBuilder BuildString<T>(IEnumerable<T> array)
    {
        return BuildString(array, new StringBuilder());
    }

使用AggregateToList().ForEach()更有效,因为后者实际上分配了一个中间列表。

答案 3 :(得分:0)

private void build_the_string<T>() /* where T:struct */ {
    T[] mData = new T[1000];
    typeof(Marshal).GetMethod("Copy", BindingFlags.Static|BindingFlags.Public,
    null, new Type[] { typeof(IntPtr), // or what myPointer really is,
    typeof(T[]), typeof(Int32), typeof(Int32) }, null)
    .Invoke(null, new object[] { myPointer, mData, 0, 1000 });
    mData.ToList().ForEach(i => descriptor_string.Append(string.Format("{0}, ", i.ToString())));
}