regarding the use of new Constraint in c# - 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.

Related

C# Generic Class<T>

How can I add a generic Type to my list?
I tried to create an object of T but this doesn't work neither.
class Bar<T> where T : IDrink
{
List<T> storage = new List<T>();
public void CreateDrink()
{
storage.Add(T); //<- This doesn't work
}
}
T is a type not an instance of that type. So you need a parameter in CreateDrink or use a factory method that returns a new instance of T.
If you want to create an instance the generic constraint must include new()
class Bar<T> where T : IDrink, new()
{
List<T> storage = new List<T>();
public void CreateDrink()
{
storage.Add(new T());
}
}
The new constraint specifies that any type argument in a generic class
declaration must have a public parameterless constructor. To use the
new constraint, the type cannot be abstract.
You can do it like:
storage.Add(Activator.CreateInstance<T>());

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.

Create generic class with internal constructor

Is it possible to construct an object with its internal constructor within a generic method?
public abstract class FooBase { }
public class Foo : FooBase {
internal Foo() { }
}
public static class FooFactory {
public static TFooResult CreateFoo<TFooResult>()
where TFooResult : FooBase, new() {
return new TFooResult();
}
}
FooFactory resides in the same assembly as Foo. Classes call the factory method like this:
var foo = FooFactory.CreateFoo<Foo>();
They get the compile-time error:
'Foo' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TFooType' in the generic type or method 'FooFactory.CreateFoo()'
Is there any way to get around this?
I also tried:
Activator.CreateInstance<TFooResult>();
This raises the same error at runtime.
You could remove the new() constraint and return:
//uses overload with non-public set to true
(TFooResult) Activator.CreateInstance(typeof(TFooResult), true);
although the client could do that too. This, however, is prone to runtime errors.
This is a hard problem to solve in a safe manner since the language does not permit an abstract constructor declaraton.
The type argument must have a
public parameterless constructor. When used together with other
constraints, the new() constraint must
be specified last.
http://msdn.microsoft.com/en-us/library/d5x73970.aspx
edit: so no, if you use new() constraint, you cannot pass that class, if you don't use new() constraint you can try using reflection to create new instance
public static TFooResult CreateFoo<TFooResult>()
where TFooResult : FooBase//, new()
{
return (TFooResult)typeof(TFooResult).GetConstructor(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new Type[] {}, null).Invoke(new object[]{});
//return new TFooResult();
}
There can be few work-arounds as below but I don't think you want to go that way!
Put switch statement inside Factory
that will create the instance based
on type of type parameter.
Each concrete implementation of FooBase will register with FooFactory passing the factory method to create it self. So FooFactory will use the internal dictionary
Extending on the similar line except mapping between type parameter and concrete implementation would be external code (xml file, configuration etc). IOC/DI containers can also help here.
public class GenericFactory
{
public static T Create<T>(object[] args)
{
var types = new Type[args.Length];
for (var i = 0; i < args.Length; i++)
types[i] = args[i].GetType();
return (T)typeof(T).GetConstructor(types).Invoke(args);
}
}

Generic type in, different generic type out using interfaces?

I'm fairly new to generics and I'm having some trouble understanding parts of how they work and also failing to get it to work the way I want.
So far, I have this;
public interface IObjectMapper
{
T MapObject<T>() where T : new();
}
public class CustomObjectMapper : IObjectMapper
{
T IObjectMapper.MapObject<T>()
{
T retObject = new T();
//do stuff......
}
}
This works fine, but I don't understand what "where T : new()" is doing. Can someone please explain? Also, for my second question - I want a second method called DemapObject that takes 2 parameters, the same generic type T from object and then a different generic type of U - U should also be the return type.
public interface IObjectMapper
{
T MapObject<T>() where T : new();
U DemapObject<T, U>() ??????? what goes here?
}
Finally, once I get the interface method for DemapObject done - how is it called from the implementation class?
public class CustomObjectMapper : IObjectMapper
{
NameValueCollection IObjectMapper.DempaObject<T, NameValueCollection>()
{
//is this right????????????
}
}
"where T :" will set a constraint on T. The constraint in this case is "new()". This means that the generic type T must have a constructor which takes no parameters.
You can stack where clauses on the same type:
class MyClass<T> where T : class, new() { }
or on different types:
class MyClass<T,U>
where T : class, new()
where U : IMyInterface
{
}
where T: new() requires that any type used as T should implement default (argument-less constructor). Otherwise it will be impossible to create an instance of T class.
For your last question: you can't make a specialized implementation of generic method. But you can make a specialized implementation of interface. Consider this:
public interface IObjectMapper<U> where U:new
{
T MapObject<T>(U arg) where T:new()
U DemapObject<T>(T arg);
}
public class CustomObjectMapper : IObjectMapper<NameValueCollection>
{
T MapObject<T>(NameValueCollection arg) where T:new(){
....
}
NameValueCollection DemapObject<T>(T arg)
{
....
}
}
IObjectMapper<NameValueCollection> mapper = new CustomObjectMapper();
And I haven't understood your second question, can you elaborate?

C# Generics - Constraints on type parameters

I'm trying to build a factory method that uses the generics feature of C#.
In this factory method I would like to constraint it to some specific classes, all of which do not have a default constructor.
Here is my example. Can someone tell me if it's possible to run it?
public class AbstractClass {
//this abstract class does not have a default constructor, nor its subclasses
public AbstractClass(SomeClassName obj) {
//use obj for initialization
}
}
//this factory class should create objects of type T that inherit
//from AbstractClass and invoke the non-default constructor
public class FactoryClass {
public static T BuildObject<T> (SomeClassName obj) where T: AbstractClass {
return new T(obj); //does not work?!?!?!
}
}
//Edit: ANSWER!!!
public static T BuildObject<T>(SomeClassUsedForTheConstructor item) where T : SomeAbstractClass {
return (T) Activator.CreateInstance(typeof (T), item);
}
I like to use Activator.CreateInstance(typeof(T)) in my generics that need to create new objects of type T. It works really well.
Look at the Type class and GetConstructor. Once you get the ConstructorInfo object, use the Invoke Method.
var x = typeof(T);
var t = x.GetConstructor(new[] {obj.GetType()});
object u = t.Invoke(<inputs>);
I don't think you can instantiate generic types without a default constructor on the constraint type.
Consider instead specifying an interface IAbstractClass, such that your factory class can set the SomeClassName parameter as a property of IAbstractClass.
Additionally, if a SomeClassName instance is required for initializing AbstractClass, consider also having an empty default constructor, but a rich initializer method defined in IAbstractClass. For example:
public interface IAbstractClass { void Initialize(SomeClassName obj); }
That way, your static BuildObject method instead does:
public static T BuildObject<T>(SomeClassName obj) where T: AbstractClass
{
T newObject = new T();
IAbstractClass ac = newObject as IAbstractClass;
ac.Initialize(obj);
}
No, what you are trying to do is not possible using the built-in generic constraints alone. The new keyword only allows you to constrain the generic type to having a default constructor.

Categories