我的问题涉及到c#以及如何访问静态成员...我真的不知道如何解释它(对于一个问题有什么不好的不是吗?)我只会给你一些示例代码:
Class test<T>{
int method1(Obj Parameter1){
//in here I want to do something which I would explain as
T.TryParse(Parameter1);
//my problem is that it does not work ... I get an error.
//just to explain: if I declare test<int> (with type Integer)
//I want my sample code to call int.TryParse(). If it were String
//it should have been String.TryParse()
}
}
谢谢你们的回答(顺便问一下:如何在没有出现错误的情况下解决这个问题)。这对你来说可能是一个非常简单的问题!
谢谢,Niklas
编辑:谢谢大家的答案!
虽然我认为try-catch短语是最优雅的,但我从vb的经验中知道它真的可能是一个无赖。我曾经用过一次,大约需要30分钟来运行一个程序,之后只花了2分钟来计算,因为我避免了尝试 - 捕获。
这就是我选择swich语句作为最佳答案的原因。它使代码更复杂,但另一方面,我认为它相对快速且相对容易阅读。 (虽然我仍然认为应该有一种更优雅的方式......也许在我学习的下一种语言中:P)
虽然如果你有其他建议,我还在等待(并愿意参加)
答案 0 :(得分:5)
问题是TryParse没有在任何地方的接口或基类上定义,所以你不能假设传入你的类的类型将具有该功能。除非你能以某种方式反对T,否则你会遇到很多。
答案 1 :(得分:3)
要访问特定类或接口的成员,您需要使用Where关键字并指定具有该方法的接口或基类。
在上面的实例中,TryParse不是来自接口或基类,因此您无法实现上述操作。最好只使用Convert.ChangeType和try / catch语句。
class test<T>
{
T Method(object P)
{
try {
return (T)Convert.ChangeType(P, typeof(T));
} catch(Exception e) {
return null;
}
}
}
答案 2 :(得分:3)
简短回答,你不能。
答案很长,你可以作弊:
public class Example
{
internal static class Support
{
private delegate bool GenericParser<T>(string s, out T o);
private static Dictionary<Type, object> parsers =
MakeStandardParsers();
private static Dictionary<Type, object> MakeStandardParsers()
{
Dictionary<Type, object> d = new Dictionary<Type, object>();
// You need to add an entry for every type you want to cope with.
d[typeof(int)] = new GenericParser<int>(int.TryParse);
d[typeof(long)] = new GenericParser<long>(long.TryParse);
d[typeof(float)] = new GenericParser<float>(float.TryParse);
return d;
}
public static bool TryParse<T>(string s, out T result)
{
return ((GenericParser<T>)parsers[typeof(T)])(s, out result);
}
}
public class Test<T>
{
public static T method1(string s)
{
T value;
bool success = Support.TryParse(s, out value);
return value;
}
}
public static void Main()
{
Console.WriteLine(Test<int>.method1("23"));
Console.WriteLine(Test<float>.method1("23.4"));
Console.WriteLine(Test<long>.method1("99999999999999"));
Console.ReadLine();
}
}
我创建了一个静态字典,其中包含我可能想要使用的每种类型的TryParse方法的委托。然后我编写了一个通用方法来查找字典并将调用传递给相应的委托。由于每个委托都有不同的类型,我只是将它们存储为对象引用,并在检索它们时将它们转换回适当的泛型类型。请注意,为了一个简单的例子,我省略了错误检查,例如检查我们是否在给定类型的字典中有一个条目。
答案 3 :(得分:2)
另一种方法,这次是混合中的一些反思:
static class Parser
{
public static bool TryParse<TType>( string str, out TType x )
{
// Get the type on that TryParse shall be called
Type objType = typeof( TType );
// Enumerate the methods of TType
foreach( MethodInfo mi in objType.GetMethods() )
{
if( mi.Name == "TryParse" )
{
// We found a TryParse method, check for the 2-parameter-signature
ParameterInfo[] pi = mi.GetParameters();
if( pi.Length == 2 ) // Find TryParse( String, TType )
{
// Build a parameter list for the call
object[] paramList = new object[2] { str, default( TType ) };
// Invoke the static method
object ret = objType.InvokeMember( "TryParse", BindingFlags.InvokeMethod, null, null, paramList );
// Get the output value from the parameter list
x = (TType)paramList[1];
return (bool)ret;
}
}
}
// Maybe we should throw an exception here, because we were unable to find the TryParse
// method; this is not just a unable-to-parse error.
x = default( TType );
return false;
}
}
下一步是尝试实施
public static TRet CallStaticMethod<TRet>( object obj, string methodName, params object[] args );
使用完整参数类型匹配等。
答案 4 :(得分:1)
你的意思是做这样的事情:
Class test<T>
{
T method1(object Parameter1){
if( Parameter1 is T )
{
T value = (T) Parameter1;
//do something with value
return value;
}
else
{
//Parameter1 is not a T
return default(T); //or throw exception
}
}
}
不幸的是,你无法检查TryParse模式,因为它是静态的 - 不幸的是,它不是特别适合于泛型。
答案 5 :(得分:1)
完全按照你要找的方法做的唯一方法就是使用反射来检查T的方法是否存在。
另一种选择是通过将类型限制为IConvertible来确保您发送的对象是可转换对象(所有基本类型都实现IConvertible)。这将允许您非常灵活地将参数转换为给定类型。
Class test<T>
{
int method1(IConvertible Parameter1){
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
}
}
你也可以通过使用'对象'类型来改变它,而不是像你原来那样。
Class test<T>
{
int method1(object Parameter1){
if(Parameter1 is IConvertible) {
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
} else {
// Do something else
}
}
}
答案 6 :(得分:1)
好的伙计们:感谢所有的鱼。现在有了你的答案和我的研究(特别是关于limiting generic types to primitives的文章),我将向你介绍我的解决方案。
Class a<T>{
private void checkWetherTypeIsOK()
{
if (T is int || T is float //|| ... any other types you want to be allowed){
return true;
}
else {
throw new exception();
}
}
public static a(){
ccheckWetherTypeIsOK();
}
}
答案 7 :(得分:1)
这不是一个真正的解决方案,但在某些情况下它可能是一个很好的选择:我们可以将另一个委托传递给泛型方法。
为了澄清我的意思,让我们举个例子。假设我们有一些通用工厂方法,它应该创建一个T实例,然后我们希望它再调用另一个方法,用于通知或其他初始化。
考虑以下简单类:
public class Example
{
// ...
public static void PostInitCallback(Example example)
{
// Do something with the object...
}
}
以下静态方法:
public static T CreateAndInit<T>() where T : new()
{
var t = new T();
// Some initialization code...
return t;
}
所以现在我们必须这样做:
var example = CreateAndInit<Example>();
Example.PostInitCallback(example);
但是,我们可以更改我们的方法以获取额外的委托:
public delegate void PostInitCallback<T>(T t);
public static T CreateAndInit<T>(PostInitCallback<T> callback) where T : new()
{
var t = new T();
// Some initialization code...
callback(t);
return t;
}
现在我们可以将呼叫更改为:
var example = CreateAndInit<Example>(Example.PostInitCallback);
显然,这仅适用于非常具体的情况。但这是最清晰的解决方案,因为我们得到了编译时的安全性,没有涉及“黑客”,代码也很简单。
答案 8 :(得分:0)
你可能不能这样做。
首先,如果有可能你需要对T进行更严格的约束,那么类型检查器可以确定T的所有可能替换实际上都有一个名为TryParse的静态方法。
答案 9 :(得分:0)
您可能需要阅读limiting generic types to primitives上的上一篇文章。这可能会为您提供一些限制可以传递给泛型的类型的指针(因为 TypeParse 显然只能用于一定数量的基元( string.TryParse 显然是例外,这没有意义。)
一旦你有了更多关于类型的句柄,你就可以尝试解析它。你可能需要一些丑陋的开关(调用正确的 TryParse ),但我认为你可以实现所需的功能。
如果您需要我进一步解释上述任何内容,请询问:)
答案 10 :(得分:0)
最佳代码:以这种方式将T限制为ValueType:
class test1<T> where T: struct
这里的“struct”表示值类型。 String是一个类,而不是值类型。 int,float,Enums都是值类型。
btw编译器不接受调用静态方法或访问“类型参数”上的静态成员,如下例所示,它不会编译:(
class MyStatic { public static int MyValue=0; }
class Test<T> where T: MyStatic
{
public void TheTest() { T.MyValue++; }
}
=&GT;错误1'T'是'类型参数',在给定的上下文中无效
SL。
答案 11 :(得分:-1)
这不是静力学的工作原理。你必须将静态视为全局类中的一种,即使它们分布在一大堆类型中。我的建议是使它成为T实例中可以访问必要的静态方法的属性。
T也是某个实际的实例,就像任何其他实例一样,您无法通过实例化的值访问该类型的静态。以下是该做什么的示例:
class a {
static StaticMethod1 ()
virtual Method1 ()
}
class b : a {
override Method1 () return StaticMethod1()
}
class c : a {
override Method1 () return "XYZ"
}
class generic<T>
where T : a {
void DoSomething () T.Method1()
}