简体   繁体   English

C#方法使用动态参数重载

[英]C# Method overloading using dynamic params

I'm trying to write a tool for serialization of values. 我正在尝试编写一个用于序列化值的工具。 And I was hoping to get some nice syntax working..... 我希望得到一些很好的语法工作.....

            float f = 9999.0f;
            ByteSerializer s = new ByteSerializer ();
            s.Write(f);

Where the params of Write() could be anything and any number: Write()的参数可以是任何数字和任何数字:

    public void Write (params dynamic[] objects)
    {

        for (int i =0;i<objects.Length;i++) {

            byteList.AddRange (GetBytes (objects[i]));

        }
    }

GetBytes() should now be called according to the type of the object that was passed: 现在应该根据传递的对象的类型调用GetBytes():

    public  byte[] GetBytes ( object v)
    {
    //Shouldn't actually do anything since it's a dummy
        return new byte[0];
    }


    public  byte[] GetBytes ( System.Single v)
    {
    //Why is this not called?

        return BitConverter.GetBytes (v);

    }

But it will always go straight for the method that takes an object as parameter. 但是它总是直接用于将对象作为参数的方法。 I initially tried (params object[]) as method parameters and found this behaviour to be rather obvious. 我最初尝试(params object [])作为方法参数,发现这种行为相当明显。 But why does dynamic[] behave the same? 但为什么动态[]表现相同?

objects[i].GetType() reports a System.Single so what's going on here? objects [i] .GetType()报告一个System.Single,那么这里发生了什么? Is what I am trying to do just not possible? 我想做的就是不可能吗?

There is no reason this shouldn't work with dynamic exactly as you described. 没有理由不应该像你描述的那样使用dynamic One of the primary features of the DLR is to do at runtime what would have been done at compile time if the types had been known then. DLR的主要功能之一是在运行时执行在编译时已完成的内容(如果已知类型)。 For example, the following program: 例如,以下程序:

public class Program
{
    public static void Main(string[] args)
    {
        WriteItems("a string", (byte)1, 3f, new object());
    }

    private static void WriteItems(params dynamic[] items)
    {
        foreach(dynamic item in items)
        {
            Write(item);
        }
    }

    private static void Write(byte b)
    {
        Console.WriteLine("Write byte: {0}", b);
    }

    private static void Write(float f)
    {
        Console.WriteLine("Write Single: {0}", f);
    }

    private static void Write(string s)
    {
        Console.WriteLine("Write string: {0}", s);
    }        

    private static void Write(object o)
    {
        Console.WriteLine("Write object: {0}", o);
    }
}

Produces the output: 产生输出:

Write string: a string 写字符串:一个字符串
Write byte: 1 写字节:1
Write Single: 3 单写:3
Write object: System.Object 写对象:System.Object

Method overloading relies on knowing at compile time the types of all the arguments. 方法重载依赖于在编译时知道所有参数的类型。 Here, you can't know the argument types at compile time - because it's dynamic - so the compiler uses the lowest common type - which is object . 在这里,您无法在编译时知道参数类型 - 因为它是dynamic - 因此编译器使用最低的公共类型 - 即object The difference between object and dynamic is that dynamic allows late binding syntax - but that doesn't help you here. objectdynamic之间的区别在于dynamic允许后期绑定语法 - 但这对您没有帮助。

If you want to call GetBytes for the correct types, you need to use reflection . 如果要为正确的类型调用GetBytes ,则需要使用反射 Specifically, you want to use GetMethod to find an overload of GetBytes that matches the type of each argument, and then call it. 具体来说,您希望使用GetMethod来查找与每个参数的类型匹配的GetBytes重载,然后调用它。 with Invoke . 使用Invoke Something like this(not tested): 像这样的东西(未经测试):

byteList.AddRange (GetType()
        .GetMethod("GetBytes", new Type[objects[i].GetType()])
        .Invoke(null, new object[objects[i]]));

The dynamic type behaves like the object type. dynamic类型的行为类似于object类型。 The only difference is that for dynamic the compiler does no type checking (so you can avoid compiler errors when working eg with COM). 唯一的区别是,对于dynamic ,编译器不进行类型检查(因此在使用COM时可以避免编译器错误)。

What you intend, can be done anyway. 无论如何,你的意图是什么。 But you must take the long road and do an explicit typechecking/cast in your for loop (a long but simple switch / case construct). 但是你必须走很长的路,并在你的for循环中做一个明确的类型检查/强制switch (一个很长但很简单的switch / case结构)。

HTH Thomas HTH托马斯

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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