如何在类声明之外声明泛型类型

时间:2020-08-05 15:44:24

标签: c#

我正在整个测试应用程序中成功使用此通用类型声明

public class TestController<TSchool>
    where TSchool: IHasStudents, IHasTeachers, IHasAdmin, new()

因为我将创建多个控制器,例如TestController<University>TestController<PrimarySchool>,所以它们的效果很好。

但是,在需要使用<TSchool> where TSchool: IHasStudents, IHasTeachers, IHasAdmin, new()的每个新类中重新键入TSchool变得非常重复。

我尝试过:

  1. public interface TSchool : IHasStudents, IHasTeachers, IHasAdmin, new()

但是编译器不喜欢new()语法

  1. public abstract class TSchool : IHasStudents, IHasTeachers, IHasAdmin, new()

也无济于事。

是否有一种方法可以在每个类声明之外声明泛型?

2 个答案:

答案 0 :(得分:1)

泛型既不是接口也不是抽象类,它是一个占位符,除了其给定的名称外没有其他含义。这就是为什么您需要告诉C#占位符实现的确切功能以便能够使用其功能,至少是那些通过接口和/或诸如new()之类的特殊对象公开的功能。

您还有很多其他选择,例如继承。除了接受通用类型,还需要基本类型。 object始终可用(尽管如果您达到该级别,则懒惰确实赢得了您的项目)。 dynamic也是一个选择。依此类推。

尽管我确实想知道为什么您需要能够实例化如此众多的类型,以至于这首先成为一个问题。也许依赖注入首先就是解决您整个问题的答案。

答案 1 :(得分:0)

您可以做的一件事就是使用嵌套类

public class TestController<TSchool> where TSchool: IHasStudents, IHasTeachers, IHasAdmin, new()
{
    //don't need to re-declare TSchool, since TSchool is accessable in the nested classes
    public class TestA
    {

    }

    public class TestB
    {

    }
}

有了这个,您将不得不考虑一种初始化嵌套类的方法,这里有一些想法。

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //initialize controller
            var testController = new TestController<University>();

            //initialize Tests and pass the reference of the controller
            var testA_1 = new TestController<University>.TestA(testController);
            var testB_1 = new TestController<University>.TestB(testController);

            //initialize the Tests without a reference of the controller
            var testA_2 = new TestController<University>.TestA();
            var testB_2 = new TestController<University>.TestB();

            //use create methods, and maybe additionally hide the public constructors
            var testA_3 = testController.CreateTestA();
            var testB_3 = testController.CreateTestB();

            //use a static TestController class, and call the public constructors
            var testA_4 = new StaticTestController<University>.TestA();
            var testB_4 = new StaticTestController<University>.TestB();

            //use a static TestController class but hide the public constructors and use create methods 
            var testA_5 = StaticTestController<University>.CreateTestA();
            var testB_5 = StaticTestController<University>.CreateTestB();
        }
    }
}

public class TestController<TSchool> where TSchool : IHasStudents, IHasTeachers, IHasAdmin, new()
{
    private TSchool _school;

    public TestController()
    {
        _school = new TSchool();
    }
    public class TestA
    {
        public TestA()
        {

        }
        public TestA(TestController<TSchool> controller)
        {
            var school = new TSchool();
            var schoolController = controller._school;
        }
    }
    public class TestB
    {
        public TestB()
        {

        }
        public TestB(TestController<TSchool> controller)
        {
            var school = new TSchool();
            var schoolController = controller._school;
        }
    }
    public TestA CreateTestA()
    {
        return new TestA(this);
    }
    public TestB CreateTestB()
    {
        return new TestB(this);
    }
}
public static class StaticTestController<TSchool> where TSchool : IHasStudents, IHasTeachers, IHasAdmin, new()
{
    private static TSchool _school;

    static StaticTestController()
    {
        _school = new TSchool();
    }

    public class TestA
    {
        public TestA()
        {
            var school = new TSchool();
            var schoolController = _school;
        }
    }

    public class TestB
    {
        public TestB()
        {
            var school = new TSchool();
            var schoolController = _school;
        }
    }

    public static TestA CreateTestA()
    {
        return new TestA();
    }
    public static TestB CreateTestB()
    {
        return new TestB();
    }
}
public class School : IHasAdmin, IHasTeachers, IHasStudents
{

}
public class University : IHasAdmin, IHasTeachers, IHasStudents
{

}
public interface IHasStudents
{

}
public interface IHasTeachers
{

}
public interface IHasAdmin
{

}