C
Join ServerC#
help
Declare method using T and where [Answered]
BObig OOF10/5/2022
This is some code from a reddit post i saw and there are some thing i dont understand.
This is the method:
This is the interface that the method uses:
From what i understand, T is used to be able to make the method more "flixble", not restricting it to a specific return type.
But when adding "where T : IStudent" - it restricts it to only return a object that inherits the IStudent interface?
Could you not just replace T with IStudent and skip the where?
Plase let me know if i got in wrong 🙂
Thanks in advance!
This is the method:
public static T CreateStudentFromEntity<T>(Student entity) where T : IStudent
{
var student = Activator.CreateInstance<T>();
student.Id = entity.Id;
student.FirstName = entity.Name;
student.Surname = entity.Surname;
student.DateOfBirth = DateTime.Parse(entity.DateOfBirth);
student.Sex = (Sex)entity.Sex;
student.Address = CreateAddressFromEntity(entity.Address);
return student;
}
This is the interface that the method uses:
public interface IStudent
{
long Id { get; set; }
string? FirstName { get; set; }
string? Surname { get; set; }
DateTime DateOfBirth { get; set; }
Sex Sex { get; set; }
string? TelephoneNumber { get; set; }
Address? Address { get; set; }
}
From what i understand, T is used to be able to make the method more "flixble", not restricting it to a specific return type.
But when adding "where T : IStudent" - it restricts it to only return a object that inherits the IStudent interface?
Could you not just replace T with IStudent and skip the where?
Plase let me know if i got in wrong 🙂
Thanks in advance!
KKouhai10/5/2022
using a constraint like this is
1 - faster
2 - allows you to have concrete return type
1 - faster
2 - allows you to have concrete return type
KKouhai10/5/2022
Let's say you have an implementation of
the returned value from
IStudent
like thispublic class InternationalStudent : IStudent
{
long Id { get; set; }
string? FirstName { get; set; }
string? Surname { get; set; }
DateTime DateOfBirth { get; set; }
string PlaceOfBirth {get; set;}
Sex Sex { get; set; }
string? TelephoneNumber { get; set; }
Address? Address { get; set; }
}
the returned value from
CreateStudentFromEntity<InternationalStudent>(entity)
would be of InternationalStudent
and you can access PlaceOfBirth
without castingPPobiega10/5/2022
Very well explained. This is because of how generics work behind the scenes - the compiler will look at the different types you pass in and actually make a "copy" of the method that works with that specific type.
Ttebeco10/5/2022
- public static T CreateStudentFromEntity<T>(Student entity) where T : IStudent
+ public static T CreateStudentFromEntity<T>(Student entity) where T : IStudent, new()
{
- var student = Activator.CreateInstance<T>();
+ var student = new T();
BObig OOF10/5/2022
Okey, thank you for the answer! Just to get my head around it - Could you say that the use of T in this case is to make a method avalible using multiple classes? And the where to restrict it to specific classes?
KKouhai10/5/2022
Yes,
In the first place, you can't instantiate an interface, so you have to use a class.
where
here is used to restrict T to IStudent implementers.In the first place, you can't instantiate an interface, so you have to use a class.
KKouhai10/5/2022
If you take a look at the code ToBeClone provided, they added another constraint
new()
this ensures that the caller has passed a class/struct implementing IStudentTtebeco10/5/2022
it make sure there's a public parameter less ctor
Ttebeco10/5/2022
meaning you can just
new
just like you call new
everydayTtebeco10/5/2022
and you get rid of
Activator
Ttebeco10/5/2022
and you still benefits from possible code optimization ... assuming there's any
Ttebeco10/5/2022
using
Activator.CreateInstance
like you did is a hack and should be avoidedTtebeco10/5/2022
generics constraint are designed to avoid that as you can see
Ttebeco10/5/2022
i love the attempt at translating french to english in the naming 😄
Ttebeco10/5/2022
string? TelephoneNumber { get; set; }
Ttebeco10/5/2022
Phone
Ttebeco10/5/2022
or
PhoneNumber
BObig OOF10/5/2022
Okok! Antother question regarding new(), i would like to say that:
requires a class that implements IStudent interface and new() interface - but new() isnt an interface. Is it instead - it require a the caller to pass an object that can be instantiated? 🙂
where T : IStudent, new()
requires a class that implements IStudent interface and new() interface - but new() isnt an interface. Is it instead - it require a the caller to pass an object that can be instantiated? 🙂
BObig OOF10/5/2022
Sorry if im asking the same questions over and over, a bit new to this :p
Ttebeco10/5/2022
public static T CreateStudentFromEntity<T>(Student entity) where T : IStudent, new()
{ ... }
public class A
{
public A(string s)
}
CreateStudentFromEntity<A>() <=== BUILD ERROR
Ttebeco10/5/2022
it will fail the build telling you that the type
A
does not contain a parameterless ctorTtebeco10/5/2022
because the only ctor for
A
require a stringBObig OOF10/5/2022
Okey! So new() set the restriction to only accept an object that includes a parameterless contructor? 🙂
KKouhai10/5/2022
Yes, it accepts a
type
that has a parameterless constructorTtebeco10/5/2022
So new()"new()" is aset the restriction
generic constraint
, yes (edited / i read too fast)Ttebeco10/5/2022
void Foo(int bar){}
Foo("abc");
Ttebeco10/5/2022
"bar must be an int"
Ttebeco10/5/2022
this is a constraint
KKouhai10/5/2022
they didn't say redirections, they said
restriction
😅Ttebeco10/5/2022
aaaaaaaaaaaaaaaaaaa
Ttebeco10/5/2022
my bad seriously
Ttebeco10/5/2022
sorry
Ttebeco10/5/2022
yeah "generic constraint" is the term, you're right
Ttebeco10/5/2022
please forgive me, i read too fast
BObig OOF10/5/2022
Haha no worries!
BObig OOF10/5/2022
Thank you guys for the great help, really appriciated 🙂
AAccord10/5/2022
✅ This post has been marked as answered!