3

コンストラクターが1つの文字列引数を取り、ToStringを実装し、以下の2つの関数を実装する型を許可するジェネリッククラスを作成する方法。

    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は、FileHelperscsvリーダーライブラリの抽象クラスです。すでにcsvのフィールドに対応するクラスがあり、FileHelpresライブラリで使用するためにConvertBaseを継承する個別のクラスを作成したくありませんでした。

4

3 に答える 3

2

コンストラクター制約(new())を使用して、空のコンストラクター以外のものに制約する方法はありません。ただし、これを回避する1つの方法は、ラムダ式を使用することです。例えば

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>し、ラムダ式を使用して、タイプのコンストラクターに転送できます。

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

OPが2.0でスタックしているため、C#2.0の実装を編集します

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

new Convert<Foo>(delegate (string s) { return new Foo(s); });
于 2011-03-31T06:57:34.217 に答える
0

できません。クラスにパラメーターのないコンストラクターがあることを強制する制約のみを作成できます。new()ご存知のように、そのための制約はです。

ToString()で定義されObject、すべてのタイプがから継承するため、すべてのタイプで使用できますObject。ただし、タイプが独自のの実装を提供するかどうかを知ることも強制することもできませんToString()

確実に、typeパラメーターは2つの特定のメソッドを実装し、それらをインターフェースに入れ、typeパラメーターをそのインターフェースに制約し、クラスにそのインターフェースを実装させます。

于 2011-03-31T06:56:13.663 に答える
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からダウンロードすることを忘れないでください

編集:Reflectionを使用して試すことができます:

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

}

注:反射は遅いので、それを考慮に入れる必要があります

于 2011-03-31T11:27:06.613 に答える