Generics in C# - new() cnstraint  
Author Message
Hatzi74





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

Hello...

 

I am trying to play a bit with the generics feature of the .Net 2.0 Framework and I ran into this "Problem"

 

I try to create a Singelton Base-Class, which will create an instance of itself if the instance is accessed. Since I want to create an Instance of <T> inside my generic Base, I need to supply a new() contraint to <T>.

This "forces" me to create a public constructor, since that what new() means.

 I think the scope of new should not be "public" but  "protected". Protected would allow me to hide the constructor from the outside world, but it would still allow the creation of the class inside the baseclass. Since I am not able to do this, a direct creation of my Baseclass is possible...

 

ExampleCode

 

public class SingeltonBase<T> where T : new()

{

#region Singlton

protected static T singleton;

public static T Instanz

{

get

{

if (singleton == null)

singleton = new T();

return singleton;

}

}

 

Edit:

Yes I know this version is not thread save... :)

 




Visual C#11  
 
 
louthy





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

new() only applies to the type parameter, not to the generic class itself.  So if you do this:

SingeltonBase<int>

Then 'int' must have a public constructor, not SingeltonBase.

I may be missing the point of what you're trying to do.   Can't you do this

 public class SingeltonBase<T> where T : new()
 {
  protected static T singleton;

  protected SingeltonBase()
  {
  }

  public static T Instance
  {
   get
   {
    if (singleton == null)
    {
     singleton = new T();
    }
    return singleton;
   }
  }
 }

 

Then you can access the singleton thus:

string test = SingletonBase<int>.Instance.ToString();

but not like this:

SingletonBase<int> test2 = new SingletonBase<int> ()

 

 


 
 
Hatzi74





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

Well thats kinda backward of what i plan to do...

I have a "handfull" of classes which i want to implement as a singelton. They SHOULD be and STAY a singelton and i dont want anyone to create a 2nd Instance of them..

So my plan way to do something like....

public class Kappa : Whatever.Global.BaseClasses.singeltonBase<Kappa>

Now "Kappa" needs a public constructor. And i dont want kappa to have one...

Hope this makes sense



 
 
louthy





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

public class Kappa : Whatever.Global.BaseClasses.singeltonBase<Kappa>

^^^ Although this line of code is legal (which I find quite hard to believe!!!).  It doesn't make much sense  

 

You're creating a class which derives from a singleton based on itself.  Surely you want something like this:

 public class SingeltonBase<T> where T : new()
 {
  protected static T singleton;

  protected SingeltonBase()
  {
  }

  public static T Instance
  {
   get
   {
    if (singleton == null)
    {
     singleton = new T();
    }
    return singleton;
   }
  }
 }

 public class Kappa
 {
  // public ctor
  public Kappa()
  {
  }
 }

 public class KappaSingleton : SingeltonBase<Kappa>
 {

 }

SingletonBase is the singleton, not Kappa, and there's nothing you can do to force Kappa to become a singleton when it's been defined with a public constructor.  SingletonBase is a seperate class to Kappa, so any instantiation happens outside of Kappa, so the constructor must be public.

I think you will just have to create your singletons the original way, and not do it with generics if you absolutely must prevent instantiation of Kappa.


 
 
Hatzi74





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

public class Kappa : Whatever.Global.BaseClasses.singeltonBase<Kappa>

^^^ Although this line of code is legal (which I find quite hard to believe!!!). It doesn't make much sense

Why would that not make sense It allows to to replace a "T" in my base class with "Kappa". And thats exactly the construct you have in a singleton declaration... A Singelton has a static method that will return an instance of the class you called... Now my goal was to "avoid" a "public" Kappa and be able to supply a SingeltonKappa "only", but this wont work with this limitation...



 
 
James Curran





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

Now "Kappa" needs a public constructor. And i dont want kappa to have

Nonsense......This compiles fine, and nothing you don't want is exposed.


public abstract class singeltonBase<T>
{
static T single;
protected abstract T Create();
public T Instance
{
get
{
if (single == null)
single = Create();
return single;
}
}
}
public class Kappa : singeltonBase<Kappa>
{
private Kappa() { }

protected override Kappa Create()
{
return new Kappa();
}

}



 
 
James Curran





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

public class Kappa : Whatever.Global.BaseClasses.singeltonBase<Kappa>

^^^ Although this line of code is legal (which I find quite hard to believe!!!). It doesn't make much sense

Of course it's legal.... It's known in the trade as the "Curiously-Recurring Template Pattern"



 
 
Paul Louth





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

Ok, the code makes sense, but the code won't work.  And never will using this method. 
 
 
Paul Louth





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

Now "Kappa" needs a public constructor. And i dont want kappa to have

Nonsense......This compiles fine, and nothing you don't want is exposed.


public abstract class singeltonBase<T>
{
static T single;
protected abstract T Create();
public T Instance
{
get
{
if (single == null)
single = Create();
return single;
}
}
}
public class Kappa : singeltonBase<Kappa>
{
private Kappa() { }

protected override Kappa Create()
{
return new Kappa();
}

}

That doesn't work either because your Instance member isn't static. So he can't write Kappa.Instance....


 
 
James Curran





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

That doesn't work either because your Instance member isn't static. So he can't write Kappa.Instance....

Heck... I merely said it compiles. The concept works for doing other things. For example, I devised one class which works like this:

class MyInteger : CompareOps<MyInteger>, IComparable<MyInt>
{
int CompareTo(MyInt x) {.....}

}

And CompareOps automatically defines;

MyInteger < MyInteger

MyInteger > MyInteger

MyInteger == MyInteger

and

MyInteger != MyInteger



 
 
Paul Louth





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

That's fine, but doesn't really help him does it
 
 
Richard Potter





PostPosted: Visual C# Language, Generics in C# - new() cnstraint Top

I think that you want to look at http://www.codeproject.com/csharp/FunWithSingletonsCS.asp.

To make an abstract singleton you are going to need reflection. Theres lots of implementations around that don't use reflection but they ALL break. Seriously, there isn't a better way that I could think of or find andywhere, I looked!

Hope this helps Smile