Using "where" in C #

Possible duplicate:
What does C # syntax mean?

Can someone clarify the difference between the following class declarations in C #:

public class SomeClass<T> where T : ISomeInterface 

vs

 public class SomeClass<ISomeInterface> 
+4
source share
1 answer

The first restricts T in the class to the type that outputs or implements this interface.

If you

 class Foo : ISomeInterface { } class Bar : ISomeInterface { } class Baz { } 

With your first definition, you could build a shared instance with the first two types, not the third.

 public class SomeClass<T> where T : ISomeInterface // your definition var obj1 = new SomeClass<Foo>(); var obj2 = new SomeClass<Bar>(); var obj3 = new SomeClass<Baz>(); // not legal, Baz does not implement ISomeInterface 

Secondly, all you have done is declare a type parameter that has the same name as the interface. This is not a general class definition that works only with an interface; it is not limited to an interface; it is just a confused name. All three classes above can be used as type arguments.

 public class SomeClass<ISomeInterface> // your definition var obj1 = new SomeClass<Foo>(); var obj2 = new SomeClass<Bar>(); var obj3 = new SomeClass<Baz>(); // legal, there is no constraint 

Edit: From the comments below

I tested " var obj3 = new SomeClass<Baz>(); " and it works, but I don't understand why. I think I donโ€™t understand this statement: "Secondly, all you have done is declare a type parameter that has the same name as the interface."

When you declare a public class definition of a public class Blah<T> , T is a placeholder. This is a type parameter that will be populated later. In your second version of the public class SomeClass<ISomeInterface> , ISomeInterface is the placeholder name! This is not an interface, it does not limit the class to using ISomeInterface , it just uses the same name as the name of the type parameter. The type argument can be any. This is the argument that the placeholder fills. var foo = new SomeClass<string>() . Here the general parameter was populated with string .

Fill in the argument by doing what I did earlier, just instantiating

 var instance = new SomeClass<string>(); 

Or you can populate it using a generic type as the base type for another type.

 class AppleSomeClass : SomeClass<Apple> 

The fact is that he agrees to use T in one situation with a type parameter, but this is only an agreement. T can be called anything instead. W. X. Apple. You have found that you can also call it the same as the existing type, which unfortunately has led to your confusion here.


Original answer continued.

With restrictions, you can restrict the type parameter to a class or universal method in order to have specific properties for it. For example, you can restrict it to a reference type or a value type.

 where T : class // reference type where T : struct // value type 

You can specify that it should be obtained from a class or implement an interface

 where T : Foo // derives from Foo where T : IFoo // implements IFoo 

And you can require it to have a constructor without parameters

 where T : new() 

And you can match them in the order above. A class or structure constraint should be the first, followed by the base type or interface, and finally the constructor.

 where T : class, IFoo where T : class, new() where T : class, Foo, new() 
+8
source

Source: https://habr.com/ru/post/1391975/


All Articles