c# generic self-referencing declarations

最后都变了- 提交于 2020-03-12 09:59:09

问题


I've been reading Albaharis' "C# 5.0 in A Nutshell" and I've encountered this in Generics section and it is said to be legal:

class Bar<T> where T : Bar<T> { ... }

And it meant nothing to me, although I've read the whole chapter carefully. I couldn't understand even a bit of it.

Can someone please explain it with some understandable naming, like:

class Person<T> where T : Person<T> { ... }

And a real-world application scenario where this usage is appropriate and useful?


回答1:


It means that T must inherit from Person<T>.

This is a typical way to create type-specific methods or properties or parameters in the base class, specific to the actual descendant.

For instance:

public abstract class Base<T> where T : Base<T>, new()
{
    public static T Create()
    {
        var instance = new T();
        instance.Configure(42);
        return instance;
    }

    protected abstract void Configure(int value);
}

public class Actual : Base<Actual>
{
    protected override void Configure(int value) { ... }
}

...

 Actual a = Actual.Create(); // Create is defined in Base, but returns Actual



回答2:


I might be a little late to the party but I want to share an unreal-world application scenario for fun :)

// self referencing list in c#
// we cant use generic type syntax: new List<List<List..
// but dynamic keyword comes to save us
// and runtime is happy with that

var list = new List<dynamic>();
list.Add(list); // the "FBI! open up" part
Console.WriteLine(list[0][0][0][0][0][0][0].Count); // 1



回答3:


It is helpful, when you work with some external library or framework(which you can't or don't want modify). For example, you have class User from this library and definitely developer, who will use it, will define CustomUser class, which is inherited from it (just for adding some custom fields). Also let's imagine, that User class has some references to another users, for example: creator and deletor (which obviously will be instances of CustomUser type). And at this case generic self-referencing declaration can help very well. We will pass type of descendant(CustomUser) as parameter to base(User) class, so at User class declaration we can set types of creator and deletor exactly as they will be at future(CustomUser), so no casting will be needed:

public class User<TCustomUser> where TCustomUser : User<TCustomUser>
{
    public TCustomUser creator {get;set;}
    public TCustomUser deletor {get;set;}

    //not convenient variant, without generic approach
    //public User creator {get;set;}
    //public User deletor {get;set;}     
}

public class CustomUser : User<CustomUser>
{
    //custom fields:
    public string City {get;set;}
    public int Age {get;set;}
}

Usage:

CustomUser customUser = getUserFromSomeWhere();
//we can do this
var creatorsAge = customUser.creator.Age;
//without generic approach:
//var creatorsAge = ((CustomUser)customUser.creator).Age;


来源:https://stackoverflow.com/questions/33430463/c-sharp-generic-self-referencing-declarations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!