c# - 从具有未知参数类型的函数调用良好重载方法

时间:2017-01-16 15:58:45

标签: c# generics dynamic struct reference

我试图从具有未知参数类型的函数中调用好的重载方法。但我总是遇到转换错误。 我怎么能这样做?

我试图不使用if来检查类型。

我尝试将我的功能更改为通用但我收到转换错误。

"Impossible to convert ref T in ref MYPROGRAM.MYCLASS.Struct1"

我的计划:

public struct Struct1
{...}

public struct Struct2
{...}

public void EditStruct(ref Struct1 StrucToEdit)
{...}

public void EditStruct(ref Struct2 StrucToEdit)
{...}

public void MyFunction<T>(ref T UnknownStruct)
{
    EditStruct(ref UnknownStruct)
}

很多。

4 个答案:

答案 0 :(得分:1)

可能有用的非常小的OO示例 - 在此示例中,使用IStructEditor接口封装了执行编辑的代码:

public static class StructEditor
{
    public static void Edit<TStruct, TEditor>(ref TStruct s)
        where TEditor : IStructEditor<TStruct>, new()
    {
        new TEditor()
            .EditStuct(ref s);
    }
}

public interface IStructEditor<T>
{
    void EditStuct(ref T s);
}

struct CostStruct
{
    public int Cost;
}

class SetCost
    : IStructEditor<CostStruct>
{
    public void EditStuct(ref CostStruct s)
    {
        s.Cost = 123;
    }
}

所以你可以按如下方式使用它:

CostStruct s = new CostStruct();
StructEditor.Edit<CostStruct, SetCost>(ref s);

意味着您可以通过实施IStructEditor来快速定义新行为!

答案 1 :(得分:1)

这是一个使用反射的简单解决方案。在这种情况下,反射结果可以非常好地缓存,性能损失不应该那么糟糕。

class Program
{
    static void Main(string[] args)
    {
            var x = new Struct1() { A = 0, B = -10 };
            var y = new Struct2() { C = 0, D = -10 };

            MyFunction(ref x);
            MyFunction(ref y);
    }


    public static void EditStruct(ref Struct1 structToEdit)
    {
        structToEdit = new Struct1() { A = 10, B = 20 };
    }

    public static void EditStruct(ref Struct2 structToEdit)
    {
        structToEdit = new Struct2() { C = 30, D = 40 };
    }

    private delegate void EditDelegate<T>(ref T obj);

    public static void MyFunction<T>(ref T unknownStruct)
    {
        Delegate d;
        if (!_dict.TryGetValue(typeof(T), out d))
        {

            d = typeof(Program).Assembly.GetTypes()
                .SelectMany(x => x.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                .Single(x => x.Name == "EditStruct" && x.GetParameters().SingleOrDefault(y => y.ParameterType.Equals(typeof(T).MakeByRefType())) != null)
                .CreateDelegate(typeof(EditDelegate<T>));
            _dict.Add(typeof(T), d);
        }

        (d as EditDelegate<T>)(ref unknownStruct);
    }

    private static readonly Dictionary<Type, Delegate> _dict = new Dictionary<Type, Delegate>(new TypeComparer());

    class TypeComparer : IEqualityComparer<Type>
    {
        public bool Equals(Type x, Type y) => x.Equals(y);

        public int GetHashCode(Type obj) => obj.GetHashCode();
    }

}

public struct Struct1
{
    public int A;
    public int B;
}

public struct Struct2
{
    public int C;
    public int D;
}

答案 2 :(得分:0)

我不会&#39;甚至理解你在做什么,但它不需要在泛型方法上进行任何转换,类型已经知道了!

只需拨打EditStruct(ref UnknownStructCasted),删除第一行即可。

参数的类型为T,而不是dynamic。只有当你打电话给你的方法

时才会这样
EditStruct(new dynamic{
   //some data
  });

Aren,你呢?

工作样本:

internal class Program
    {
        public enum WhatToDo
        {
            Something,
            SomethingElse
        }

        public static void MyMethod(WhatToDo what)
        {
            switch (what)
            {
                case WhatToDo.Something:
                    Struct1 param1 = new Struct1();
                    MygenericMethod(param1);
                    break;
                case WhatToDo.SomethingElse:
                    Struct2 param2 = new Struct2();
                    MygenericMethod(param2);
                    break;
            }
        }

        public static void MygenericMethod<T>(T someParam) where T : struct
        {
        }

        public struct Struct1
        {
        }

        public struct Struct2
        {
        }
    }

答案 3 :(得分:0)

如果您可以找到结构的通用界面,请考虑以下内容:

class Program
{
    static void Main(string[] args)
    {
        IStruct s1 = new Struct1();
        IStruct s2 = new Struct2();

        EditStruct(ref s1);
        EditStruct(ref s2);
    }

    static void EditStruct(ref IStruct target)
    {
        target.Name = Guid.NewGuid().ToString();
    }
}

public interface IStruct
{
    string Name { get; set; }
}

public struct Struct1 : IStruct
{
    public string Name { get; set; }
}

public struct Struct2: IStruct
{
    public string Name { get; set; }
}