C# 如何从模板调用方法?
我有一个C#WinForms代码,其中有几个不同的C# 如何从模板调用方法?,c#,templates,generics,data-structures,struct,C#,Templates,Generics,Data Structures,Struct,我有一个C#WinForms代码,其中有几个不同的结构,它们都以相同的方式运行。因此,我不再编写用于添加或删除项的单个函数,而是尝试使用模板 例如,这里有一个struct和相应的列表,我用来存储它的对象: public struct Alias { public string alias; public string aliasSource; public static bool IsValid(...); //This function exists in all t
结构
,它们都以相同的方式运行。因此,我不再编写用于添加或删除项的单个函数,而是尝试使用模板
例如,这里有一个struct
和相应的列表
,我用来存储它的对象
:
public struct Alias
{
public string alias;
public string aliasSource;
public static bool IsValid(...); //This function exists in all the structs
};
List<Alias> aliases;
这有什么办法吗?我所有的
struct
都有一个IsValid
函数,使用相同的设置,因此重复编写相同的代码似乎很愚蠢,以防我在这里不使用模板…你不能这样做。唯一的选项是为泛型参数定义where
约束,使其属于某种接口或基类类型。但是,无论是使用结构还是使用静态成员,都无法做到这一点。如果将结构更改为类,则可以执行以下操作:
public interface IValidatable
{
bool IsValid(out outputError);
}
public class Alias : IValidatable
{
public string alias;
public string aliasSource;
public bool IsValid(out outputError) { ... };
};
现在可以应用约束:
private void AddValidatableItem<T>(T item, List<T> list)
where T : IValidatable
{
string outputError;
if (!item.IsValid(out outputError))
{
MessageBox.Show(outputError);
return;
}
if (list.Contains(item))
{
MessageBox.Show("ERROR 82ha5jb :: Item already exists");
return;
}
list.Add(item);
}
不能使用约束告诉编译器对象上将存在静态方法。如果确实需要是静态的,则需要使用反射来调用该方法:
var methodInfo = typeof(T).GetMethod("IsValid", BindingFlags.Static|BindingFlags.Public);
if (methodInfo != null)
{
object[] parameters = new object[] { genericStructItem, null };
if ((bool)methodInfo.Invoke(null, parameters))
{
// It's valid!
}
else
{
string error = (string)parameters[1];
}
}
C的泛型与C++中的模板有很大的不同,虽然语法看起来相似。
当你说T.IsValid(genericStructItem, out outputError);
听起来您希望编译器将T
替换为Alias
以提供
Alias.IsValid(genericStructItem, out outputError);
这不是泛型的工作方式。您需要找到另一种方法来调用IsValid
,例如反射或向结构添加公共接口
<>我也会强烈地考虑使用类而不是结构。我不知道选择结构的原因,但一般来说,不使用结构的原因有很多,尤其是如果它们需要是可变的。虽然语法看起来很相似,但是, C泛型与C++中的模板有很大的不同。我希望一个名为IsValid()的方法需要访问该对象。是的,我想这是一种看待它的方式。不过,我使用它的方式是,当我需要验证输入本身时(以后创建结构实例时基于输入),因此需要事先进行验证,这就是为什么在这种情况下需要使用静态方法。您能告诉我您在
(…)
中放了什么吗?下面是我使用的完整行:var isValid=(bool)methodInfo.Invoke(genericStructItem,out outputError)代码>,但这给了我一个错误:与'System.Reflection.MethodBase.Invoke(object,object[])匹配的最佳重载方法有一些无效参数
,我将更新我的代码。此外,这篇文章还很好地解释了通过带有out参数的反射进行的静态方法调用:不确定该场景如何适合我的场景。我找到了需要放置什么来代替object,object[]
,但我的问题是out
参数不起作用(就像您指出的线程中的问题一样)。但是,该页面上的解决方案使用C#定义的函数来使用TryParse(即getryparsemethodinfo()
),这是我无法做到的,因为在我自己的函数中是有效的。应该行的,刚刚看到代码。看起来还可以,但我认为您已将out
参数置零。难道不可能以某种方式将部分也提取出来吗?这对于非静态方法很好,但不适用于静态方法。@itsme86请仔细阅读我答案的第一段
public static void AddValidatableItem<T>(this List<T> list, T item)
where T : IValidatable
aliases.AddValidatableItem(newAlias);
var methodInfo = typeof(T).GetMethod("IsValid", BindingFlags.Static|BindingFlags.Public);
if (methodInfo != null)
{
object[] parameters = new object[] { genericStructItem, null };
if ((bool)methodInfo.Invoke(null, parameters))
{
// It's valid!
}
else
{
string error = (string)parameters[1];
}
}
T.IsValid(genericStructItem, out outputError);
Alias.IsValid(genericStructItem, out outputError);