简体   繁体   English

泛型:如何检查T的确切类型,没有T的对象

[英]Generics: How to check the exact type of T, without object for T

How can i check/evaluate the exact type of T without an object for T. I know my question maybe confusing but consider this... 如何在没有T的对象的情况下检查/评估T的确切类型。我知道我的问题可能令人困惑,但请考虑一下......

 public abstract class Business
    {
        public abstract string GetBusinessName();
    }

    public class Casino : Business  
    {
        public override string GetBusinessName()
        {
            return "Casino Corp";
        }
    }

    public class DrugStore : Business 
    {
        public override string GetBusinessName()
        {
            return "DrugStore business";
        }
    }


    public class BusinessManager<T> where T : Business
    {
        private Casino _casino;
        private DrugStore _drugStore;

        public string ShowBusinessName()
        {
            string businessName;
            if (T == Casino) // Error: How can I check the type?
            {
                _casino = new Casino();
                businessName = _casino.GetBusinessName();
            }
            else if (T == DrugStore) // Error: How can I check the type?
            {
                _drugStore = new DrugStore();
                businessName = _drugStore.GetBusinessName();
            }

            return businessName;

        }
    }

I just want to have something like this on the client. 我只是想在客户端上有这样的东西。

    protected void Page_Load(object sender, EventArgs e)
    {
        var businessManager = new BusinessManager<Casino>();
        Response.Write(businessManager.ShowBusinessName());

        businessManager = new BusinessManager<DrugStore>();
        Response.Write(businessManager.ShowBusinessName());
    }

Notice that I actually didnt create the actual object for Casino and Drugstore when I call the BusinessManager, I just pass it as generic type constraint of the class. 请注意,当我调用BusinessManager时,我实际上没有为Casino和Drugstore创建实际对象,我只是将其作为类的泛型类型约束传递。 I just need to know exactly what Type i am passing BusinessManager to know what exactly the Type to instantiate . 我只需要知道我正在传递什么类型的BusinessManager来知道要实例化的Type究竟是什么 Thanks... 谢谢...

PS: I don't want to create separate specific BusinessManager for Casino and Drugstore.. PS:我不想为Casino和Drugstore创建单独的特定BusinessManager。

You can also comment about the design.. thanks.. 您还可以对设计发表评论..谢谢..

ADDITIONAL: and what if class Casino and DrugStore is an ABSTRACT CLASS =) 附加:如果类Casino和DrugStore是抽象类=如果=)

You can write 你可以写

if(typeof(T) == typeof(Casino))

but really this type of logic is a code smell. 但实际上这种逻辑是一种代码味道。

Here's one way around this: 这是解决这个问题的一种方法:

public class BusinessManager<T> where T : Business, new() {
    private readonly T business;
    public BusinessManager() {
        business = new T();
    }
}

but personally I'd prefer 但我个人更喜欢

public class BusinessManager<T> where T : Business {
    private readonly T business;
    public BusinessManager(T business) {
        this.business = business;
    }

    public string GetBusinessName() { 
        return this.business.GetBusinessName();
    }
}

You should do 你应该做

public class BusinessManager<T> where T : Business, new()
...

T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;

I don't know about C# syntax, but is it not possible to do: 我不知道C#语法,但是不可能这样做:

public class BusinessManager<T> where T : Business, new()
    {
        private T _business;

        public string ShowBusinessName()
        {
            string businessName;
            _business = new T();
            return _business.GetBusinessName();
        }
    }

Since other guys have already shown various answers to your first question, I would like to address the second one: design. 由于其他人已经对你的第一个问题给出了各种答案,我想谈谈第二个问题:设计。

1. Role of BusinessManager 1. BusinessManager角色

Actual role of the BusinessManager class in your example is not too clear. BusinessManager类在示例中的实际角色不太清楚。 Since this class is generic, and it shouldn't be concerned with the actual type of T , then it does nothing more than add another unnecessary layer between the Business class and the rest of the program. 由于这个类是通用的,并且它不应该关注T的实际类型,因此它只是在Business类和程序的其余部分之间添加另一个不必要的层。

In other words, you can simply use: 换句话说,您可以简单地使用:

Business casino = new Casino();
Response.Write(casino.GetBusinessName());

Business drugStore = new DrugStore();
Response.Write(drugStore.GetBusinessName());

Wrapping this in another generic class doesn't help you a lot. 将它包含在另一个泛型类中对你没有多大帮助。 On the other hand, if you want to have some common functionality for all these classes, you can either add it directly to your abstract class, or extract an interface and create extension methods for that interface. 另一方面,如果要为所有这些类提供一些通用功能,可以将其直接添加到抽象类中,也可以提取接口并为该接口创建扩展方法。

2. Using properties for getters 2.使用吸气剂的属性

Second thing, using a property is more appropriate when you have a simple getter method. 第二,使用简单的getter方法时,使用属性更合适。 In other words, you should replace GetBusinessName() method with a Name property (I also omitted the "Business" from the name because it is not necessary: 换句话说,你应该用Name属性替换GetBusinessName()方法(我也从名称中省略了“Business”,因为没有必要:

public interface IBusiness
{
    string Name { get; }
}

public abstract class Business : IBusiness
{
    public abstract string Name { get; }
}

public class Casino : Business  
{
    public override string Name
    {
        get { return "Casino Corp"; }
    }
}

public class DrugStore : Business 
{
    public override string Name
    {
        get { return "DrugStore business"; }
    }
}

And then you can use it like this: 然后你可以像这样使用它:

IBusiness casino = new Casino();
Response.Write(casino.Name);

IBusiness drugStore = new DrugStore();
Response.Write(drugStore.Name);

Also, you can see that I have introduced a IBusiness interface. 此外,您可以看到我已经引入了IBusiness接口。 The reason for doing so is to allow you to implement this interface in more diverse ways. 这样做的原因是允许您以更多样化的方式实现此接口。 Right now, you will try to derive all your classes from the abstract Business class, and try to extract as much of the common functionality in the abstract class (that's the purpose of the class). 现在,您将尝试从抽象Business类派生所有类,并尝试在抽象类中提取尽可能多的常用功能(这是类的目的)。

But extracting lots of common functionality comes with a cost: there is always a possibility that you will come up with a need to create a class which isn't derived from Business . 但是,提取大量常用功能需要付出代价:您总是有可能需要创建一个不是Business 派生的类。 If you are accessing all these methods through the IBusiness interface, then other parts of your program won't care if that implementation is derived from Business or not. 如果您通过IBusiness接口访问所有这些方法,那么程序的其他部分将不关心该实现是否来自Business

Since GetBusinessName really applies to the type and not instances of the type, you might consider using DescriptionAttribute (or your own BusinessNameAttribute) instead of an overridden property and have your BusinessManager get the business name from the attribute. 由于GetBusinessName确实适用于类型而非类型实例,因此您可以考虑使用DescriptionAttribute(或您自己的BusinessNameAttribute)而不是重写属性,并让BusinessManager从属性中获取业务名称。

[Description("Casino Corp")]
public class Casino : Business  
{
}

Now you no longer need to instantiate the business just to gets its name. 现在,您不再需要实例化业务只是为了得到它的名字。 To get the description, you use: 要获得描述,请使用:

    public string ShowBusinessName()
    {
        var attribute = Attribute.GetCustomAttribute(typeof(T), typeof(DescriptionAttribute)) as DescriptionAttribute;
        if (attribute == null)
            return "Unknown business";

        return attribute.Description;
    }

You can do something like this: 你可以这样做:

if (typeof(T) == typeof(SomeType))
{
    // Same
}

define a BusinessManager class as bellow: BusinessManager类定义为:

public class BusinessManager<T> where T : Business
{ 
    Business biz;
    public BusinessManager()
    {
        biz = new T();
    }

    public string ShowBusinessName()
    {
        return biz.GetBusinessName();
    }
}

and use it as bellow: 并使用它如下:

    var businessManager = new BusinessManager<Casino>();
    Response.Write(businessManager.ShowBusinessName());

    var anotherBusinessManager = new BusinessManager<DrugStore>();
    Response.Write(businessManager.ShowBusinessName());

The way you using you will lost encapsulation 你使用它的方式将失去封装

In VB.net you can use the GetType pseudo-function on a generic type parameter to get a reflection Type object. 在VB.net中,您可以在泛型类型参数上使用GetType伪函数来获取反射Type对象。 I would guess C# should have an equivalent. 我猜C#应该有一个等价物。 If for whatever reason you can't use something like that, you could create an array of 0 elements of the desired type, and then check the type of that array. 如果由于某种原因你不能使用类似的东西,你可以创建一个包含所需类型的0个元素的数组,然后检查该数组的类型。 That would probably be cheaper than instantiating an element of the unknown type. 这可能比实例化未知类型的元素便宜。

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

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