简体   繁体   English

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

[英]How to declare a generic type outside of class declaration

I am using this generic type declaration with success throughout my testing application我在整个测试应用程序中都成功使用了这个泛型类型声明

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

Beacuse I will create multiple controllers like TestController<University> or TestController<PrimarySchool> and these work great.因为我将创建多个控制器,例如TestController<University>TestController<PrimarySchool> ,这些都很好用。

However, it gets very repetitive to retype the <TSchool> where TSchool: IHasStudents, IHasTeachers, IHasAdmin, new() in every new class that I need to use TSchool但是,在我需要使用TSchool的每个新 class 中重新键入<TSchool> where TSchool: IHasStudents, IHasTeachers, IHasAdmin, new()

I have tried:我努力了:

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

But the compiler does not like the new() syntax但是编译器不喜欢new()语法

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

Also to no avail.也无济于事。

Is there a way I can declare the generic type outside of every class declaration?有没有办法可以在每个 class 声明之外声明泛型类型?

A generic type is neither an interface nor an abstract class, it's a placeholder with no meaning other than the name its given.泛型类型既不是接口也不是抽象 class,它是一个占位符,除了给定的名称之外没有任何意义。 It's why you need to tell C# what exactly that placeholder implements to be able to use its functions, at least those exposed through interfaces and/or special things like new() .这就是为什么您需要告诉 C# 该占位符究竟实现了什么才能使用其功能,至少是那些通过接口和/或诸如new()之类的特殊事物公开的功能。

You have plenty of other choices, for example inheritance.您还有很多其他选择,例如 inheritance。 Instead of accepting generic types, require a base type instead.而不是接受泛型类型,而是需要一个基类型。 object is always available (though if you go to that level, laziness has really won over your project). object始终可用(尽管如果您将 go 提升到该级别,那么懒惰确实赢得了您的项目)。 dynamic is also a choice. dynamic也是一种选择。 And so on.等等。

Though I do wonder why you need to be able to instantiate so many of your types that this becomes an issue in the first place.尽管我确实想知道为什么您需要能够实例化这么多类型,以至于这首先成为一个问题。 Perhaps dependency injection is the answer to your entire problem in the first place.也许依赖注入首先是您整个问题的答案。

One thing you could do is use nested classes您可以做的一件事是使用嵌套类

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
    {

    }
}

With this you will have to think about a way to initialize the nested classes here are some ideas.有了这个,您将不得不考虑一种初始化嵌套类的方法,这里有一些想法。

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
{

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM