带有字符串参数的构造函数的通用约束?

Posted

技术标签:

【中文标题】带有字符串参数的构造函数的通用约束?【英文标题】:Generic constraint for Constructor with string argument? 【发布时间】:2011-03-31 06:52:59 【问题描述】:

如何创建一个泛型类,该类允许具有构造函数的类型采用一个字符串参数并实现 ToString 并实现如下两个函数。

    class Convert<T>:ConverterBase
        where T:new()
    

        public override object StringToField(string from)
        
            try
            
                return new T(from);
            
            catch (ArgumentException exception)
            
                ThrowConvertException(from, exception.Message);
                return null;
            
        

        public override string FieldToString(object from)
        
            return from.ToString();
        

    

注意: ConvertBase 是 FileHelpers csv 阅读器库中的一个抽象类。我已经有与我在 csv 中的字段对应的类,不想创建单独的类来继承 ConvertBase 以便与 FileHelpres 库一起使用。

【问题讨论】:

【参考方案1】:

没有办法使用构造函数约束 (new()) 来约束空构造函数以外的任何内容。解决此问题的一种方法是使用 lambda 表达式。例如

class Convert<T>:ConverterBase 
  private Func<string, T> _factory;
  public (Func<string, T> factory) 
    _factory = factory;
  

  public override object StringToField(string from) 
    try 
      return _factory(from);
     ...
  

现在我可以创建 Convert&lt;T&gt; 的实例并使用 lambda 表达式转发到该类型的构造函数

new Convert<Foo>(s => new Foo(s));

EDIT C# 2.0 实现,因为 OP 卡在 2.0 上

public delegate TResult Func<T, TResult>(T arg);

new Convert<Foo>(delegate (string s)  return new Foo(s); );

【讨论】:

我被 c#2.0 卡住了,我想我不能使用 Func 它只是一个代表。自己创建:public delegate TResult Func&lt;out TResult&gt;() @yesraaj 您可以自己定义Func&lt;&gt; 并使用旧的 C# 委托样式语法。我用一个例子更新了我的答案【参考方案2】:

您好,您可以创建一个基类来存储转换器函数并实现这两个成员,之后您可以从它继承并且只提供字符串到对象的转换

public abstract class Convert<T>:ConverterBase

    private Func<string, T> ConverterFunction get;set;

    protected Convert(Func<string, T> converterFunction)
    
        ConverterFunction = converterFunction;
    

    public override object StringToField(string from)
    
        try
        
            return ConverterFunction(from);
        
        catch (ArgumentException exception)
        
            ThrowConvertException(from, exception.Message);
            return null;
        
    

    public override string FieldToString(object from)
    
        return from.ToString();
    


稍后创建一些简单的派生类,例如:

public class ConvertMyClass:ConverterBase<MyClass>

    public ConvertMyClass()
        :base(from => new MyClass(from)
     
    

希望这会有所帮助 :) 请记住从以下网址下载最新的稳定版本: http://teamcity.codebetter.com/viewLog.html?buildId=lastSuccessful&buildTypeId=bt66&tab=artifacts&guest=1

编辑:您可以尝试使用反射:

class Convert<T>:ConverterBase


    public override object StringToField(string from)
    
        try
        
            return Activator.CreateInstance(typeof(T), from);
        
        catch (ArgumentException exception)
        
            ThrowConvertException(from, exception.Message);
            return null;
        
    

    public override string FieldToString(object from)
    
        return from.ToString();
    


注意:反射很慢,所以你必须考虑到这一点

【讨论】:

我的意图是完全消除像这样的类 ConvertMyClass,前提是 Type T 有一个带有一个字符串参数的构造函数,这样我就可以使用[FieldConverter(typeof(Convert&lt;HasRequiredFns&gt;))] @yesraaj:所以你需要使用反射来获取带有一个参数字符串的构造函数并使用Activator动态调用它,我刚刚更新了anwser【参考方案3】:

你不能。您只能创建一个强制要求您的类具有无参数构造函数的约束。如您所知,其约束是new()

ToString() 可用于每种类型,因为它是在Object 上定义的,并且每种类型都继承自Object。但是,您无法知道或强制执行您的类型是否提供了自己的 ToString() 实现。

为了确保类型参数实现了两个特定的方法,将它们放入一个接口并将类型参数约束到该接口并让您的类实现该接口。

【讨论】:

以上是关于带有字符串参数的构造函数的通用约束?的主要内容,如果未能解决你的问题,请参考以下文章

在Java泛型类中,在构造函数级别添加额外的通用约束?

如何检查类型是不是提供无参数构造函数?

带有构造函数参数的 RegisterSingleton

JMeter JunitSampler 无法找到带有字符串参数的构造函数

是否可以有一个带有 1 个未声明类型的输入参数的构造函数?

C#的泛型的类型参数可以有带参数的构造函数的约束方式吗?