devNull
devNull

Reputation: 4219

Is there a way to access class nested in generic class without specifying type parameter?

Given the following set of classes:

public abstract class User<T> where T : Permission
{
    public ICollection<T> Permissions { get; set; }

    public class Client : User<Permission.Client> { }

    public class Admin : User<Permission.Admin> { }
}

public abstract class Permission
{
    public class Client : Permission { }

    public class Admin : Permission { }
}

You're able to create an instance of User<T>.Client while passing a type parameter to User<T> other than what the class itself uses in implementing User<T>. In the following example, User<T>.Client is being created with T as Permission.Admin, even though the class actually implements User<T> with Permission.Client:

var client = new User<Permission.Admin>.Client();
client.Permissions.Add(new Permission.Client());
client.Permissions.Add(new Permission.Admin()); // cannot convert from 'Permission.Admin' to 'Permission.Client'

There is at least the build error that prevents adding an Admin permission to the Client user. However, the usage can be misleading since the type parameter being passed to User<T> seems to be superfluous.


Question: Is there a way to create an instance of a User<T>.Client without having to specify type parameter T on User (e.g. User.Client)?

Here's a dotnetfiddle with the full example.

Upvotes: 0

Views: 62

Answers (1)

Mike-314
Mike-314

Reputation: 351

Aside from what everyone has said in the comments, about the nested classes, if you want your user permissions to container both client and admin permissions, you need to be using a collection of type Permission

public ICollection<Permission> Permissions { get; set; } = new List<Permission>();

That'll fix your example, but not make your code any easier to follow.

Update: Is there a reason why your code couldn't be more like this:

public class Program
{
    public static void Main(string[] args)
    {
        var client = new ClientUser();
        client.Permissions.Add(new ClientPermission());
        //This should fail because a client user can't have admin permissions
        client.Permissions.Add(new AdminPermission()); // cannot convert from 'AdminPermission' to 'ClientPermission'
    }


    public abstract class User<T> where T : Permission
    {
        public ICollection<T> Permissions { get; set; } = new List<T>();
    }

    public class ClientUser : User<ClientPermission> { }

    public class AdminUser : User<AdminPermission> { }

    public abstract class Permission
    {
    }

    public class ClientPermission : Permission { }

    public class AdminPermission : Permission { }
}

Upvotes: 1

Related Questions