Conditional generic constructor type in C #?

Say you have a general class Foo:

public class Foo<T> {

    public T Data {
        get;
        protected set;
    }

}

Is it possible to define a constructor that is applicable only if it Tinherits (or is) a specific type.

For example, Tthis is int:

    public Foo () {
        this.Data = 42;
    }

Type restriction must be checked at compile time. This may be useful for optimization. Say, for example, you have IEnumerable<T>one and you want to create a "cache" (since LINQ queries can be quite expensive). Now, if it is IEnumerable<T>already IList<T>, it is useful not to copy the data. On the other hand, if it is really a LINQ query, another constructor can store the data in an array.


, , Foo (, IntFoo) :

public class IntFoo : Foo<int> {

    public IntFoo () {
        this.Data = 42;
    }

}

, private ( protected). , , , ?

+4
4

, . .

internal static class FooHelper
{
    private static class DefaultData<T>
    {
        public static T Value = default(T);
    }

    static FooHelper()
    {
        DefaultData<int>.Value = 42;
        DefaultData<string>.Value = "Hello World";
    }

    // From @JeffreyZhao:
    //
    // Use a static method to trigger the static constructor automatically,
    // or we need to use RuntimeHelpers.RunClassConstructor to make sure
    // DefaultData is corrected initialized.
    //
    // The usage of RuntimeHelpers.RunClassConstructor is kept but commented.
    // Using GetDefault<T>() is a better approach since static Foo() would be
    // called multiple times for different generic arguments (although there 
    // no side affect in this case).
    //
    // Thanks to @mikez for the suggestion.
    public static T GetDefault<T>()
    {
        return DefaultData<T>.Value;
    }
}

public class Foo<T>
{
    /* See the comments above.
    static Foo()
    {
        RuntimeHelpers.RunClassConstructor(typeof(FooHelper).TypeHandle);
    }
     */

    public T Data { get; protected set }

    public Foo()
    {
        Data = FooHelper.GetDefault<T>();
    }
}

, .

. ITypeConverter<T> TypeConverter, :

public interface ITypeConverter<T>
{
    bool CanConvertTo<TTarget>();
    TTarget ConvertTo(T value);
}

:

public class LongConverter : ITypeConverter<long>
{
    private static class Op<TTarget>
    {
        public static Func<long, TTarget> ConvertTo;
    }

    static LongConverter()
    {
        Op<string>.ConvertTo = v => v.ToString();
        Op<DateTime>.ConvertTo = v => new DateTime(v);
        Op<int>.ConvertTo = v => (int)v;
    }

    public TTarget ConvertTo<TTarget>(T value)
    {
        return Op<TTarget>.ConvertTo(value);
    }
}

, .

+11
  public class Foo<T>
  {
      public T Data
      {
          get;
          protected set;
      }

            public Foo()
            {
                switch (Type.GetTypeCode(Data.GetType()))
                {
                    case TypeCode.Int16:
                    case TypeCode.Int32:
                    case TypeCode.Int64:
                        Data = (T)Convert.ChangeType(42, typeof(T));
                        break;
                    default:
                        break;
                }

            }

        }

,

public class Foo<T>
{

    public T Data
    {
        get;
        protected set;
    }

    public Foo()
    {
        switch (Type.GetTypeCode(Data.GetType()))
        {
            case TypeCode.Boolean:
                Data = ConvertValue<T>(true); 
                break;
            case TypeCode.DateTime:
                Data = ConvertValue<T>("01/01/2014"); 
                break;
            case TypeCode.Double:
                Data = ConvertValue<T>(0.5); 
                break;
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
                Data = ConvertValue<T>(32); 
                break;
            case TypeCode.String:
                Data = ConvertValue<T>("Test");
                break;
            default:
                break;
        }

    }
    private static T ConvertValue<T>(object value)
    {
        return (T)Convert.ChangeType(value, typeof(T));
    }
}
+4

, .

public class Foo<T>
{

    public T Data
    {
        get;
        protected set;
    }

    public Foo()
    {
        if (Data is int)
            Data = (T)(object)42;
    }
}

:

Console.WriteLine("int = {0}", new Foo<int>().Data);
Console.WriteLine("double = {0}", new Foo<double>().Data);
Console.WriteLine("string = {0}", new Foo<string>().Data);

:

int = 42
double = 0
string =
+3

( ):

public class Foo<T> {

  public T Data { get; private set; }

  public static Foo<T> Create(T value)
  {
     return new Foo<T> { Data = value };
  }

  public static Foo<int> From(int value)
  {
     return new Foo<int> { Data = 42 * value };
  }
}

:

  void Main()
  {
    var v = Foo<int>.Create(1); 
    var s = Foo<string>.Create("test");
  }

- , ( Foo<int> Create<int>(int value) Create(int value), .

, , 2 (, Create<U>() , (, where U:class where U:struct).

+3
source

Source: https://habr.com/ru/post/1542411/


All Articles