What is the preferred syntax for restricting the derivation of a general class?

The documented derivation constraint uses the where T : clause, and the sample code I use is

 public class TwoThingsIPC<T> where T : IPassClass { ... } 

where IPassClass is the interface.

The third-party user code I'm using is in the format

 public class TwoThingsIPC<IPassClass> { ... } 

Both lead to the same behavior in my code, but are they the same, and if not, what's the difference?

+7
generics c #
source share
5 answers

They do not match. The second declaration is misleading:

 public class TwoThingsIPC<IPassClass> { ... } 

does not limit the type to IPassClass . It uses a poor choice of names for a general argument. There is nothing stopping you from creating an instance of TwoThingsIPC<int> - the IPassClass links in the class code will simply be "replaced" with int . one

On the other hand, a variable of type TwoThingsIPC<IPassClass> , for example:

 TwoThingsIPC<IPassClass> myVar = new TwoThingsIPC<IPassClass>(); 

restricts type to IPassClass interface.


1 This is not what is actually happening, but I do not have a better explanation.

+9
source share

Your example is incorrect. An identifier is an identifier, and T and IPassClass are both only identifiers. What's in the name? So:

 public class TwoThingsIPC<IPassClass> 

really the same as:

 public class TwoThingsIPC<T> 

except that in the first case, you use an incomprehensible name really for the type parameter that you declare there.

You may have thought of a different situation when you will choose between:

 public class AnotherClass : TwoThingsIPC<IPassClass> 

and

 public class AnotherClass<TPass> : TwoThingsIPC<TPass> where TPass : IPassClass 

where in both cases the IPassClass must be a type that is already declared elsewhere.

Note that the first one is not a generic class that has a generic class as a base class. The second is a generic class (since the TPass that is declared is its type parameter), which has a base class that depends on its own generic parameter.

+2
source share

In a generic type definition, the where clause is used to indicate type restrictions that can be used as arguments to the type parameter defined in the generic declaration.

In addition to interface restrictions, the where clause may include a base class constraint, which states that the type must have the specified class as the base class (or be that class itself) to be used as a type argument for this generic type

If you want to examine an element in a general list to determine whether it is valid or to compare it with some other element, the compiler should have some guarantee that the operator or method that it should call will be supported by any type of argument, which can be specified by client code. This guarantee is obtained by applying one or more restrictions to the definition of your general class.

Literature:
http://msdn.microsoft.com/en-us/library/bb384067.aspx
http://msdn.microsoft.com/en-us/library/d5x73970.aspx

+1
source share

"where" is a generic type restriction.

Taken from http://msdn.microsoft.com/en-us/library/bb384067.aspx

In the definition of a generic type, the where clause is used to indicate a restriction on types that can be used as arguments for the type parameter defined in the generic declaration. For example, you can declare a common class MyGenericClass so that a parameter of type T implements the IComparable interface:

Here are some examples:

 public class TwoThingsIPC<T> where T : IPassClass { } public class TestClass { } public class TestClass2 : IPassClass { } var test1 = new TwoThingsIPC<TestClass>(); //this will not compile var test2 = new TwoThingsIPC<TestClass2>(); //this will compile because it implements IPassClass 

Other examples:

 public class TwoThingsIPC<T> where T : class { } public class TestClass { } var test1 = new TwoThingsIPC<int>(); //this will not compile because it is a value type //these will compile because they are reference types var test2 = new TwoThingsIPC<TestClass>(); var test3 = new TwoThingsIPC<List<TestClass>>(); internal delegate void DWork(); var test4 = new TwoThingsIPC<DWork>(); 

Literature:

http://msdn.microsoft.com/en-us/library/bb384067.aspx

http://msdn.microsoft.com/en-us/library/d5x73970.aspx

0
source share

Thanks for the help; collect relevant answers and make sure that I have the right facts:

Asawyer's comment on the original post points to the difference between the constraint and the argument for generics ... while D Stanly illustrates how to use the argument where the constraint required can lead to inaccurate type comparisons.

Jeppe Stig Nielsen found out that soon I would like to write classes that inherit from a common class with an interface argument. I asked him where to find examples of how to do this.

All along, solid support for the transition with some dependency injection ... Thanks again!

0
source share

All Articles