C# generic constraint for Type to be castable
Asked Answered
A

4

14

Is there a way with C# generics to limit a type T to be castable from another type?

Example:
Lets say I am saving information in the registry as a string, and when I restore the information I would like to have a function that looks something like that:

static T GetObjectFromRegistry<T>(string regPath) where T castable from string 
{
    string regValue = //Getting the registry value...
    T objectValue = (T)regValue;
    return objectValue ;
}
Avictor answered 24/7, 2013 at 6:46 Comment(1)
There is no such constraints in .NETDisjunctive
D
9

There is no such type of constraints in .NET. There is only six types of constraints available (see Constraints on Type Parameters):

  • where T: struct type argument must be a value type
  • where T: class type argument must be a reference type
  • where T: new() type argument must have a public parameterless constructor
  • where T: <base class name> type argument must be or derive from the specified base class
  • where T: <interface name> type argument must be or implement the specified interface
  • where T: U type argument supplied for T must be or derive from the argument supplied for U

If you want to cast string to your type, you can do casting to object first. But you can't put constraint on type parameter to make sure this casting can occur:

static T GetObjectFromRegistry<T>(string regPath)
{
    string regValue = //Getting the regisstry value...
    T objectValue = (T)(object)regValue;
    return objectValue ;
}

Another option - create interface:

public interface IInitializable
{
    void InitFrom(string s);
}

And put it as constraint:

static T GetObjectFromRegistry<T>(string regPath) 
  where T: IInitializable, new()
{
    string regValue = //Getting the regisstry value...   
    T objectValue = new T();
    objectValue.InitFrom(regValue);
    return objectValue ;
}
Disjunctive answered 24/7, 2013 at 6:50 Comment(0)
J
1

While the literal answer is no, the correct answer in the spirit of the question is yes.


Test test = new Test();
test.TestMethod();

class A
{
    public string someField;
}

class B : IConvertibleFrom<A>
{
    public string convertedField;

    public void TakeDataFrom(A a)
    {
        this.convertedField = a.someField;
        //etc
    }
}

class C
{
}

interface IConvertibleFrom<T>
{
    void TakeDataFrom(T t);
}

class Test  
{

    // here is our constraint
    public T FromA<T>() where T: IConvertibleFrom<A>, new()
    {
        var a = new A();
        a.someField = "it works";
        T t = new T();
        t.TakeDataFrom(a);
        return t;
    }

    public void TestMethod()
    {
        var b = FromA<B>();
        Console.WriteLine(b.convertedField); // prints "it works"
        // var c = FromA<C>(); // Compiler error because C does not implement IConvertibleFrom<A>
    }
}

Jagir answered 2/6 at 15:7 Comment(0)
C
0

Types are determined during compilation. You can't change the types during runtime. It is possible to cast object to its base or child class

Ref -

Difference between object a = new Dog() vs Dog a = new Dog()

Cortes answered 24/7, 2013 at 6:49 Comment(1)
I realize that Types are determined at compilation time. but at compilation time you can also now the type reference passed to the function. (in the same manner that. string a = "abc", a[0] will work while (a as object)[0] won't ) So I don't really see how this answers the question...Avictor
V
0

Constraints spell out like "the type of T must either be of type U or inherit type U", so the constraint you are looking for isn't doable.

everything is "castable" to String anyway, through .ToString() (YMMV)

Valente answered 24/7, 2013 at 7:5 Comment(1)
YMMV explained: .ToString() is more or less an inbuilt debugging-feature. "It converts an object to its string representation so that it is suitable for display." - MSDN. I strongly advise against (ab-)using it for casting.Able

© 2022 - 2024 — McMap. All rights reserved.