我试图从具有未知参数类型的函数中调用好的重载方法。但我总是遇到转换错误。 我怎么能这样做?
我试图不使用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)
}
很多。
答案 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; }
}