简体   繁体   English

在.NET中对类型参数进行约束有什么意义(基类和接口约束)

[英]What's the point of having constraints for type parameters in .NET (base class and interface constraints)

I'm working on a small class library at work, and it naturally involves using generics for this task. 我正在研究工作中的小型类库,它自然会涉及使用泛型来完成这项任务。 But there is this thing that I don't really understand with generics: Why would I need to use generic type parameters, and then constrain the the type parameter to a specific base class or interface. 但是有些东西我对泛型并不是很理解:为什么我需要使用泛型类型参数,然后将type参数约束到特定的基类或接口。

Here's an example to what I mean: 这是我的意思的一个例子:

public class MyGenericClass<T> where T : SomeBaseClass
{
    private T data;
}

And here's the implementation without generics 这是没有泛型的实现

public class MyClass
{
    private SomeBaseClass data;
}

Are these two definitions the same (if yes, then i don't see the advatage of using generics here)? 这两个定义是否相同(如果是,那么我在这里看不到使用泛型的优点)?

If not, what do we benefit from using generics here? 如果没有,我们在这里使用泛型有什么好处?

As with almost all uses of generics, the benefit comes to the consumer. 与仿制药的几乎所有用途一样,消费者也会受益。 Constraining the type gives you the same advantages that you get by strongly typing your parameter (or you can do other things like ensure that there's a public parameterless constructor or ensure that it's either a value or reference type) while still retaining the niceties of generics for the consumer of your class or function. 约束类型可以获得与强类型参数相同的优势(或者您可以执行其他操作,例如确保存在无参数构造函数或确保它是值或引用类型),同时仍保留泛型的细节您的班级或职能的消费者。

Using generics also, for example, allows you to obtain the actual type that was specified , if that's of any particular value. 例如,使用泛型也允许您获取指定的实际类型(如果具有任何特定值)。

This example is a little contrived, but look at this: 这个例子有点人为,但看看这个:

public class BaseClass
{
    public void FunctionYouNeed();
}

public class Derived : BaseClass
{
    public void OtherFunction();
}

public class MyGenericClass<T> where T: BaseClass
{
    public MyGenericClass(T wrappedValue)
    {
        WrappedValue = wrappedValue;
    }

    public T WrappedValue { get; set; }

    public void Foo()
    {
        WrappedValue.FunctionYouNeed();
    }
}

...

var MyGenericClass bar = new MyGenericClass<Derived>(new Derived());

bar.Foo();

bar.WrappedValue.OtherFunction();

The difference is that the former defines the new class as a specific type; 不同之处在于前者将新类定义为特定类型; the latter simply defines a plain class with a field of that type. 后者只是定义了一个具有该类型字段的普通类。

It's all about type safety. 这都是关于类型安全的。 Using generics you can return a concrete type (T) instead of some base type which defines the API you need in your generic class. 使用泛型,您可以返回一个具体类型(T),而不是一些基类型,它定义了泛型类中所需的API。 Therefore, the caller of your method won't have to cast the result to the concrete type (which is an error-prone operation). 因此,您的方法的调用者不必将结果强制转换为具体类型(这是一个容易出错的操作)。

The main difference is in usage. 主要区别在于使用方法。 In the first case, the usage can have: 在第一种情况下,用法可以包括:

MyGenericClass<SomeDerivedClass> Variable
Variable.data.SomeDerivedProperty = X

And so that when you use that class, you can still access anything from SomeDerivedClass without casting back to it. 因此,当您使用该类时,您仍然可以从SomeDerivedClass访问任何内容而无需返回它。

The second example will not allow this. 第二个例子不允许这样做。

MyClass.data = SomeDerivedClassInstance
MyClass.data.SomeDerivedProperty = X //Compile Error
((SomeDerivedClass)MyClass.data).SomeDerivedProperty = X //Ewwwww

You will have to cast back up to the SomeDerivedClass (which is unsafe) to use something specific to the derived class. 您将不得不强制转换为SomeDerivedClass(这是不安全的)以使用特定于派生类的内容。

I don't think that there is a huge amount of difference except that the generic version is constraining your Class , whereas the second is just a constraint on a member of the class. 我认为除了泛型版本限制你的 ,而第二个只是对类成员的约束之外,存在巨大差异。 If you added more members and methods to your first Class, you would have the same constraint in place. 如果您向第一个类添加了更多成员和方法,那么您将拥有相同的约束。

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

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