Generic class and Constraint - c#

I am working with Generic class and Constraint. Following is my class.
public class GenericList<T> where T : new()
{
private Node head;
// constructor
public GenericList()
{
head = null;
}
}
when i create object with integer it works fine
GenericList<int> list = new GenericList<int>();
But when i try with string it gives me following compile time error.
GenericList<string> list1 = new GenericList<string>();
'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'GenericTest.GenericList'
also when i passed reference parameter like any custom class it works fine.
What is the problem with string?

String Class does not have a public parameterless constructor..that is why the new() constraint is not applicable to it.
Read Constraints on Type Parameters (C# Programming Guide):
where T : new()
The type argument must have a public parameterless constructor. When
used together with other constraints, the new() constraint must be
specified last.

It is pointless for String type to have public parameterless constructor because String is immutable, which means that if String would have this constructor then it would have to create an empty string object and that is just stupid, because after creation you can not change it.

Related

Which is the preferred syntax for a Generic Class Derivation Constraint?

The documented derivation constraint uses a where T : clause and the sample code that I'm tinkering with is
public class TwoThingsIPC<T> where T : IPassClass
{ ...
}
where IPassClass is an interface.
Code from a third-party that I am using has the format
public class TwoThingsIPC<IPassClass>
{ ...
}
Both result in the same behaviour in my code, but are they the same and if not what is the difference?
They are not the same. The second declaration is misleading:
public class TwoThingsIPC<IPassClass>
{ ...
}
does not constrain the type to the IPassClass interface. It uses a poor choice of names for a generic argument. There's nothing preventing you from creating an instance of TwoThingsIPC<int> - the IPassClass references in the class's code would just be "replaced" by int.1
On the other hand, a variable of type TwoThingsIPC<IPassClass>, for example:
TwoThingsIPC<IPassClass> myVar = new TwoThingsIPC<IPassClass>();
does constrain the type to the IPassClass interface.
1 That's not what really happens, but I don't have a better explanation yet.
Your example is wrong. An identifier is an identifier, and T and IPassClass are both just identifiers. What's in a name? So:
public class TwoThingsIPC<IPassClass>
is really the same as:
public class TwoThingsIPC<T>
except in the first case you use a really confusing name for the type parameter you declare there.
Maybe you were thinking of another situation where you will find yourself choosing between:
public class AnotherClass : TwoThingsIPC<IPassClass>
and:
public class AnotherClass<TPass> : TwoThingsIPC<TPass>
where TPass : IPassClass
where in both cases IPassClass must be a type that is already declared elsewhere.
Note that the first of these is a non-generic class that has a generic class as its base class. The second one is a generic class (since TPass which is declared there is its type parameter) which has a base class that depends on its own generic parameter.
In a generic type definition, the where clause is used to specify constraints on the types that can be used as arguments for a type parameter defined in a generic declaration.
In addition to interface constraints, a where clause can include a base class constraint, which states that a type must have the specified class as a base class (or be that class itself) in order to be used as a type argument for that generic type
If you want to examine an item in a generic list to determine whether it is valid or to compare it to some other item, the compiler must have some guarantee that the operator or method it has to call will be supported by any type argument that might be specified by client code. This guarantee is obtained by applying one or more constraints to your generic class definition.
References:
http://msdn.microsoft.com/en-us/library/bb384067.aspx
http://msdn.microsoft.com/en-us/library/d5x73970.aspx
The 'where' is a generic type constraint.
Taken from http://msdn.microsoft.com/en-us/library/bb384067.aspx
In a generic type definition, the where clause is used to specify
constraints on the types that can be used as arguments for a type
parameter defined in a generic declaration. For example, you can
declare a generic class, MyGenericClass, such that the type parameter
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>();
References:
http://msdn.microsoft.com/en-us/library/bb384067.aspx
http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Thanks for the help; to put together the pertinent responses and to make sure I have the facts correct:
The Asawyer comment to the original post points out the difference between a constraint and argument for generics ... while D Stanly illustrates how using an argument where a constraint is required can lead to sloppy type matching.
Jeppe Stig Nielsen figured out that I soon will want to write classes that inherit from the generic class with an interface argument. I have asked him where to find examples of how to do that.
All together solid support to get going with some dependency injection...
Thanks again!

Generic method with class & new() keyword

public class ViewModelBaseEx<T> : ViewModelBase where T : class, new()
{
//...........
}
I found a class like this in a sample. In this class what is the meaning of portion "where T : class, new()". what is the use of class, new() in this method definition.
It means that T must be a reference type (normally a class, interface, delegate or array) (but not a struct) and that it must have a public parameterless constructor T() (so this will rule out all the previous with exception of class).
It is a generic type constraint.
It specifies that whatever T is, it must be a reference type (a class) and it must have a public default parameterless constructor (new()).
This allows people to do this:
var x = new T();
Without the new() constraint, that isn't possible.
Basically class, new() are adding constraints.
class means that it should be of type class (structs etc are not allowed)
new() represents that it must have a public constructor which takes no parameters.
It means that T must be a reference (class) type and that it must also have a public default constructor.
See here for more information: http://msdn.microsoft.com/en-us/library/d5x73970.aspx
class here is to constraint T to be of Class only, i.e, cannot be structure and other value types.
new() here is to constraint T has to have an empty constructor.
for more information on type constraint, look at the MSDN: http://msdn.microsoft.com/en-us/library/d5x73970.aspx
"class" basically means that "T" is a class type (could be a struct as well => primitive type). The "new()" syntax means that "T" is a class that has an empty constructor so in your class you could do something like:
var obj = new T();

must be a non-abstract type with a public parameterless constructor in redis

When I save an object, I get the following error :
must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'ServiceStack.Redis.RedisClient.Store<T>(T)
RedisClass.GetInstance().Store(msg); // Error here
RedisClass.GetInstance().Save();
As this is a third party's class, I can't edit it. How do I save this object?
Could you create a wrapper around the third party object to call its constructor, then store the wrapper?
E.g.
public class MyWrapper
{
public ThirdPartyObject ThirdPartyInstance { get; set; }
public MyWrapper()
{
ThirdPartyInstance = new ThirdPartyObject("Constructors");
}
}
The error is caused by that IBasicPersistenceProvider.Store<T>() has the new() generic constraint. Instead, try using IBasicPersistenceProvider<T>.Store():
RedisClass.GetInstance().As<ThirdPartyClass>().Store(msg);

regarding the use of new Constraint in c#

i never use new Constraint because the use is not clear to me. here i found one sample but i just do not understand the use. here is the code
class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
public class ItemFactory2<T> where T : IComparable, new()
{
}
so anyone please make me understand the use of new Constraint with small & easy sample for real world use. thanks
This constraint requires that the generic type that is used is non-abstract and that it has a default (parameterless) constructor allowing you to call it.
Working example:
class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
which obviously now will force you to have a parameterless constructor for the type that is passed as generic argument:
var factory1 = new ItemFactory<Guid>(); // OK
var factory2 = new ItemFactory<FileInfo>(); // doesn't compile because FileInfo doesn't have a default constructor
var factory3 = new ItemFactory<Stream>(); // doesn't compile because Stream is an abstract class
Non-working example:
class ItemFactory<T>
{
public T GetNewItem()
{
return new T(); // error here => you cannot call the constructor because you don't know if T possess such constructor
}
}
In addition to Darin's answer, something like this would fail because Bar does not have a parameterless constructor
class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
class Foo : ItemFactory<Bar>
{
}
class Bar
{
public Bar(int a)
{
}
}
Actual error is: 'Bar' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'ItemFactory<T>'
The following would also fail:
class ItemFactory<T>
{
public T GetNewItem()
{
return new T();
}
}
Actual error is: Cannot create an instance of the variable type 'T' because it does not have the new() constraint
The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor.
quoted from the official website
You can read new() as if it is an interface with a constructor. Just like that IComparable specifies that the type T has a method CompareTo, the new constraint specifies that the type T has a public constructor.
In your example, the constraint acts on <T> in the class declaration. In the first case, it requires that the generic T object has a default (parameterless) constructor. In the second example, it requires that T should have a default, parameterless constructor and that it must implement the IComparable interface.

What does new() mean?

There is an AuthenticationBase class in WCF RIA Services. The class definition is as follows:
// assume using System.ServiceModel.DomainServices.Server.ApplicationServices
public abstract class AuthenticationBase<T>
: DomainService, IAuthentication<T>
where T : IUser, new()
What does new() mean in this code?
It's the new constraint.
It specifies that T must not be abstract and must expose a public parameterless constructor in order to be used as a generic type argument for the AuthenticationBase<T> class.
Using the new() keyword requires a default constructor to be defined for said class. Without the keyword, trying to class new() will not compile.
For instance, the following snippet will not compile. The function will try to return a new instance of the parameter.
public T Foo <T> ()
// Compile error without the next line
// where T: new()
{
T newInstance = new T();
return newInstance;
}
This is a generic type constraint. See this MSDN article.
It means that a type used to fill the generic parameter T must have a public and parameterless constructor. If the type does not implement such a constructor, this will result in a compile-time error.
If the new() generic constraint is applied, as in this example, that allows the class or method (the AuthenticationBase<T> class in this case) to call new T(); to construct a new instance of the specified type. There is no other way, short of reflection (this includes using System.Activator, to construct a new object of a generic type.

Categories