具有字符串参数的Constructor的通用约束?

时间:2011-03-31 06:52:59

标签: c# generics c#-2.0 constraints filehelpers

如何创建一个泛型类,它允许类型构造函数接受一个字符串参数并实现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库一起使用。

3 个答案:

答案 0 :(得分:2)

无法使用构造函数约束(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<T>的实例并使用lambda表达式转发到类型

的构造函数
new Convert<Foo>(s => new Foo(s));

编辑 C#2.0实施,因为OP坚持2.0

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

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

答案 1 :(得分:0)

你做不到。您只能创建一个强制执行的约束,即您的类具有无参数构造函数。正如您所知,对此的约束是new()

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

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

答案 2 :(得分:0)

您可以在那里创建一个存储转换器函数并实现两个成员的基类,之后您可以继承该成员并仅将字符串提供给对象转换

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();
    }

}

注意:反射很慢,因此您必须考虑到这一点

相关问题