Generic class where type 可以解析字符串

Generic class where type can Parse strings

我想创建一个泛型 class,其中 class 的类型可以解析字符串。

我想将此 class 用于任何具有静态函数 Parse(string) 的 class, 像 System.Int32、System.Double,但也像 System.Guid 这样的 class。他们都有一个静态的解析函数

所以我的 class 需要一个 where 子句来将我的泛型类型限制为具有 Parse 函数的类型

我想这样使用它:

class MyGenericClass<T> : where T : ??? what to do ???
{
     private List<T> addedItems = new List<T>()

     public void Add(T item)
     {
          this.AddedItems.Add(item);
     }

     public void Add(string itemAsTxt) 
     {
         T item = T.Parse(itemAsTxt);
         this.Add(item);
     }
}

where子句写什么?

你根本不能在编译时这样做。除了名称之外,所有这些方法没有 任何 共同点。它们既没有在任何公共接口中定义,也没有相同的参数。

想象一下,您有自己的方法,但意外地使用了该名称,但做的事情却完全不同。此外,它也是一个实例方法:

class MyType
{
    void Parse() { ... }
}

如您所见,该方法甚至没有 any 参数,因此很难在 - 例如 - int.Parse(myString)[ 之间找到任何共同逻辑=12=]myInstanceOfMyType.Parse()`。

但即使 if 你也可以做到。你会用 item 做什么?没有太多,因为他们之间没有任何共同点。特别是不可能调用 methpd,因为它们完全不同。

但是您可以在运行时使用类似的方法循环所有类型:

var types = allAssemblies.SelectMany(x => x.GetTypes())
                .Where(x => x.GetMethod("Parse") != null);

但请注意,如果每个类型的名称中存在多个方法,这会产生 AmbiguousMatchException,这就是方法重载的时候。

我可能误解了你的问题,但这能解决问题吗?

    static void Main(string[] args)
    {
        Guid g = DoParse<Guid>("33531071-c52b-48f5-b0e4-ea3c554b8d23");

    }

    public static T DoParse<T>(string value) 
    {
        T result = default(T);
        MethodInfo methodInfo = typeof(T).GetMethod("Parse");
        if (methodInfo != null)
        {

            ParameterInfo[] parameters = methodInfo.GetParameters();
            object classInstance = Activator.CreateInstance(typeof(T), null);

            object[] parametersArray = new object[] { value };
            result = (T)methodInfo.Invoke(methodInfo, parametersArray);

        }
        return result;
    }

我对使用反射进行解析的答案不满意。

我更喜欢类型安全的解决方案,这样编译器会抱怨缺少 Parse 函数。

通常您会限制为具有接口的 class。但正如其他人所说,没有通用接口。想想看,我不需要接口,我需要一个可以调用的函数

所以我的解决方案是坚持要求创建者向解析函数提供一个委托,该委托将解析字符串以键入 T

class MyGenericClass<T>
{
    public MyGenericClass(Func<string, T> parseFunc)
    {
         this.parseFunc = parseFunc;
    }

    private readonly Func<string, T> parseFunc;

    public void Add(string txt) 
    {
        this.Add(parseFunc(txt));
    }
}

用法:

MyGenericClass<Guid> x = new MyGenericClass<Guid>(txt => Guid.Parse(txt));
MyGenericClass<int> y = new MyGenericClass<int> (txt => System.Int32.Parse(txt));

答案比我想象的要简单