Reputation: 10456
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 ;
}
Upvotes: 14
Views: 5466
Reputation: 176
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>
}
}
Upvotes: 1
Reputation: 236228
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 typewhere T: class
type argument must be a reference typewhere T: new()
type argument must have a public parameterless constructorwhere T: <base class name>
type argument must be or derive from the specified base classwhere T: <interface name>
type argument must be or implement the specified interfacewhere T: U
type argument supplied for T must be or derive from the argument supplied for UIf 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 ;
}
Upvotes: 9
Reputation: 23300
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)
Upvotes: 0
Reputation: 5627
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()
Upvotes: 0