473,516 Members | 2,956 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How to return generic abstract class ?

8 New Member
Hi there!

I have something like this:
Expand|Select|Wrap|Line Numbers
  1.     abstract class BaseClass<T>
  2.     {
  3.         protected BaseClass(){}
  4.     }
  5.  
  6.     class Class1 : BaseClass<Class1>
  7.     {
  8.         public static Class1 Instance = new Class1();
  9.         private Class1(){}            
  10.     }
  11.  
  12.     class Class2 : BaseClass<Class2>
  13.     {
  14.         public static Class2 Instance = new Class2();
  15.         private Class2(){}        
  16.     }
  17.  
  18.     ...
  19.     public BaseClass<T> Method<T>(int z) where T: BaseClass<T>
  20.     {
  21.         switch(z)
  22.         {
  23.             case 1: 
  24.                 return Class1.Instance;
  25.             case 2:
  26.                 return Class2.Instance;
  27.         }
  28.     }
  29.  
That is very important that those classes cannot be instantiated since their construstors are private so we cannot do like

`public BaseClass<T> Method<T>(int z) where T: BaseClass<T>,` **new()**

How can I use abstract class as return type ?? I just can not work this out. Would appreciate for any assisstance here.
Mar 9 '09 #1
12 5230
vekipeki
229 Recognized Expert New Member
Please use CODE tags when posting, it makes your code much easier to read.

How about something like this:
Expand|Select|Wrap|Line Numbers
  1. abstract class BaseClass<T>
  2. {
  3.     public abstract T Instance { get; }
  4. }
  5.  
  6. class Class1 : BaseClass<Class1>
  7. {
  8.     private Class1() { }
  9.  
  10.     readonly Class1 _instance = new Class1();
  11.     public override Class1 Instance
  12.     {
  13.         get { return _instance; }
  14.     }
  15. }
  16.  
  17. class Class2 : BaseClass<Class2>
  18. {
  19.     private Class2() { }
  20.  
  21.     readonly Class2 _instance = new Class2();
  22.     public override Class2 Instance
  23.     {
  24.         get { return _instance; }
  25.     }
  26. }
Compiler cannot know know that Instance is of type T (or BaseClass<T>), if it is static, so you have to do it like this.
Mar 9 '09 #2
kkris1983
8 New Member
@vekipeki
Thank You for response,
Sorry I am newbie here, next time I will use CODE tags. My question concerns
Expand|Select|Wrap|Line Numbers
  1.  BaseClass<T> Method<T>(int z) where T: BaseClass<T>
method how to make it work... Properties cannot be inherited in my solution it is a bit complicated. Is there a way to make that Method<T> work like I wrote it ?
Mar 9 '09 #3
vekipeki
229 Recognized Expert New Member
The important thing to notice here is that Class1.Instance is of type Class1, while Class2.Instance is of type Class2. Since they are both static and are not defined in any interface or parent abstract class, for C# compiler they are completely different.

You are telling compiler that T should be derived from BaseClass<T>, but you are not telling him that T is Class1 or Class2, so it doesn't want to allow that.

What would happen if your code would compile without errors, and somebody wrote this:
Expand|Select|Wrap|Line Numbers
  1. BaseClass<Class1> obj = Method<Class1>(2);
Your Method<T> would then return BaseClass<Class2>, which is not BaseClass<Class1>.

Properties cannot be inherited in my solution it is a bit complicated.
Why not?

I think the way you're trying to code it right now is a bit complicated, so try to explain what you are trying to do and then maybe it would be easier to point you in the right direction.

From your code, it looks like Method<T> should belong to the abstract class, in which case you need to be able to get an instance of T somehow (either by having a public constructor, or by using an abstract property).
Mar 9 '09 #4
kkris1983
8 New Member
You are right there I just noticed that simple skeleton lacked on some things... ok there is whole code:

Expand|Select|Wrap|Line Numbers
  1. public abstract class StorageBaseAbstract<T> where T : StorageBaseAbstract<T>
  2.     {
  3.         #region Singleton
  4.  
  5.         private static T _instance;
  6.         protected StorageBaseAbstract() { }
  7.  
  8.         protected static bool Initialised
  9.         {
  10.             get
  11.             {
  12.                 return _instance != null;
  13.             }
  14.         }
  15.  
  16.         protected static void Init(T newInstance)
  17.         {
  18.             if (newInstance == null)
  19.                 throw new ArgumentNullException();
  20.  
  21.             _instance = newInstance;
  22.         }
  23.  
  24.         protected static T UniqueInstance
  25.         {
  26.             get
  27.             {
  28.                 return Initialised ? SingletonCreator.instance : null;
  29.             }
  30.         }
  31.  
  32.         private class SingletonCreator
  33.         {
  34.             internal static readonly T instance = _instance;
  35.             static SingletonCreator() { }
  36.         }
  37.  
  38.         #endregion
  39.  
  40.         public abstract Guid Put(byte[] bytaArray);
  41.         public abstract byte[] Get(Guid guid);
  42.     }
  43.  
  44.     public sealed class StorageMemory : StorageBaseAbstract<StorageMemory>
  45.     {
  46.         public static StorageMemory Instance
  47.         {
  48.             get
  49.             {
  50.                 if (!Initialised)
  51.                     Init(new StorageMemory());
  52.                 return UniqueInstance;
  53.             }
  54.         }
  55.  
  56.         private StorageMemory() { }
  57.  
  58.         #region Members
  59.  
  60.         public override Guid Put(ToProcessObject obj)
  61.         {
  62.             return UniqueUserState.Instance.SaveObject(obj);
  63.         }
  64.  
  65.         public override ToProcessObject Get(Guid guid)
  66.         {
  67.             return UniqueUserState.Instance.LoadObject(guid);
  68.         }
  69.  
  70.         #endregion
  71.     }
  72.  
  73. public sealed class StorageDataBase : StorageBaseAbstract<StorageDataBase>
  74. {}
  75.  
  76. public sealed class StorageFileSystem : StorageBaseAbstract<StorageFileSystem>
  77. {}
  78.  
and I would like to use that "StorageBaseAbstract<T>" class in factory pattern like:

Expand|Select|Wrap|Line Numbers
  1. public StorageBaseAbstract<T> GetStorage<T>(StorageType type) where T : StorageBaseAbstract<T>
  2.         {
  3.             switch (type)
  4.             {
  5.                 case StorageType.DataBase:
  6.                     return StorageDataBase.Instance;
  7.                 case StorageType.FileSystem:
  8.                     return StorageFileSystem.Instance;
  9.                 case StorageType.Memory:
  10.                     return StorageMemory.Instance;
  11.                 default:
  12.                     throw new ArgumentException("Invalid type.", "type");
  13.             }
  14.         }
  15.  
I hope now it is clear what I want to do.
Of course I can make it works like:

Expand|Select|Wrap|Line Numbers
  1. public object GetStorage(StorageType type)
  2. {
  3.             switch (type)
  4.             {
  5.                 case StorageType.DataBase:
  6.                     return StorageDataBase.Instance;
  7.                 case StorageType.FileSystem:
  8.                     return StorageFileSystem.Instance;
  9.                 case StorageType.Memory:
  10.                     return StorageMemory.Instance;
  11.                 default:
  12.                     throw new ArgumentException("Invalid type.", "type");
  13.             }
  14.         }
  15.  
but that is not my point.
Mar 9 '09 #5
kkris1983
8 New Member
By the way... the thing You wrote about
"Method<T> should belong to the abstract class, in which case you need to be able to get an instance of T"

that code:
Expand|Select|Wrap|Line Numbers
  1. public BaseClass<T> Method<T>(int z) where T: BaseClass<T>
  2.  
says itself ( " where T: BaseClass<T>" ) that T must be BaseClass or class that inherits it... so in switch statement we return Class1 or Class2 that are descendants so it should work, or I am wrong ?
Mar 9 '09 #6
vekipeki
229 Recognized Expert New Member
To call the GetStorage<T> method, you already need to know the type of T, so it isn't actually a factory.

I still don't understand why Instance needs to be static. If it was public and abstract in your base class (StorageBaseAbstract<T>), then you could simply get the singleton using:

Expand|Select|Wrap|Line Numbers
  1. StorageDataBase db = StorageDataBase.Instance;
or

Expand|Select|Wrap|Line Numbers
  1. StorageDataBase db = StorageBaseAbstract<StorageDataBase>.Instance;

But the first thing that bothers me is that it is not very obvious what the StorageBaseAbstract class does. It looks like you are only using it to save a static singleton instance of your derived classes. Furthermore, none of its methods is public, so it really doesn't do anything.

Why don't you just write:
Expand|Select|Wrap|Line Numbers
  1. public class StorageMemory
  2. {
  3.     private static readonly StorageMemory _singleton
  4.              = new StorageMemory();
  5.     public static StorageMemory Instance
  6.     {
  7.         get
  8.         {
  9.             return _singleton;
  10.         }
  11.     }
  12.  
  13.     private StorageMemory() { }
  14. }
Mar 9 '09 #7
kkris1983
8 New Member
the thing was I wanted to make an abstract class that its descendants will be instantly Singleton one. That is solution from:
http://www.c-sharpcorner.com/UploadF...Singleton.aspx

My problem has solution:
there it is...
http://social.msdn.microsoft.com/For...4-2476cb64c994

Thank You for Your kind assisstance!
Mar 9 '09 #8
vekipeki
229 Recognized Expert New Member
But the example in the first article looks like this:

Expand|Select|Wrap|Line Numbers
  1. public class Singleton<T> where T : class
  2. {
  3.     Singleton() { }
  4.  
  5.     class SingletonCreator
  6.     {
  7.         static SingletonCreator() { }
  8.  
  9.         private static T CreateInstance()
  10.         {
  11.             ConstructorInfo constructorInfo = typeof(T).GetConstructor(BindingFlags.Instance |
  12.                 BindingFlags.NonPublic, Type.DefaultBinder, Type.EmptyTypes, null);
  13.  
  14.             if (constructorInfo != null)
  15.             {
  16.                 return constructorInfo.Invoke(null) as T;
  17.             }
  18.             else
  19.             {
  20.                 // alternatively, throw an exception indicating the type parameter
  21.                 // should have a private parameterless constructor
  22.                 return null;
  23.             }
  24.         }
  25.  
  26.         internal static readonly T instance = CreateInstance();
  27.     }
  28.  
  29.  
  30.     public static T UniqueInstance
  31.     {
  32.         get { return SingletonCreator.instance; }
  33.     }
  34. }
Then if you add a parameterless ctor to your class
Expand|Select|Wrap|Line Numbers
  1. public class DatabaseStorage
  2. {
  3.      private DatabaseStorage() {}
  4. }
You can simply access (or create) the singleton using:
Expand|Select|Wrap|Line Numbers
  1. DatabaseStorage dbStorage = Singleton<DatabaseStorage>.UniqueInstance;
But note that UniqueInstance is public and created in abstract class.

Writing code to create an instance each time (in each derived class) doesn't make any sense (StorageMemory.Instance, for example) - what's the point in having an abstract class then?

Note that you also don't need to inherit from Singleton<T>, it is only a helper class to avoid writing singleton code multiple times.
Mar 9 '09 #9
kkris1983
8 New Member
"it is only a helper class to avoid writing singleton code multiple times" that is what i wanted to achieve there... yeah now I get Your point with that public property in abstract class, that is correct, thank You for advice
Mar 9 '09 #10
kkris1983
8 New Member
@vekipeki
I meant preceding example
Expand|Select|Wrap|Line Numbers
  1. public abstract class AbstractGenericSingleton<T> where T : AbstractGenericSingleton<T>
  2.  
  3. {
  4.  
  5.     private static T _instance;
  6.  
  7.  
  8.  
  9.     protected static bool Initialised
  10.  
  11.     {
  12.  
  13.         get
  14.  
  15.         {
  16.  
  17.             return (_instance != null);
  18.  
  19.         }
  20.  
  21.     }
  22.  
  23.  
  24.  
  25.     protected static T UniqueInstance
  26.  
  27.     {
  28.  
  29.         get
  30.  
  31.         {
  32.  
  33.             if (Initialised)
  34.  
  35.             {
  36.  
  37.                 return SingletonCreator.instance;
  38.  
  39.             }
  40.  
  41.             else
  42.  
  43.             {
  44.  
  45.                 return null;
  46.  
  47.             }
  48.  
  49.         }
  50.  
  51.     }
  52.  
  53.  
  54.  
  55.     protected AbstractGenericSingleton() { }
  56.  
  57.  
  58.  
  59.     protected static void Init(T newInstance)
  60.  
  61.     {
  62.  
  63.         if (newInstance == null) throw new ArgumentNullException();
  64.  
  65.  
  66.  
  67.         _instance = newInstance;
  68.  
  69.     }
  70.  
  71.  
  72.  
  73.     class SingletonCreator
  74.  
  75.     {
  76.  
  77.         static SingletonCreator() { }
  78.  
  79.  
  80.  
  81.         internal static readonly T instance = _instance;
  82.  
  83.     }
  84.  
  85.  
  86.  
  87. }
  88.  
  89.  
  90.  
  91. public sealed class ReadyForGenericSingleton : AbstractGenericSingleton<ReadyForGenericSingleton>
  92.  
  93. {
  94.  
  95.     public static ReadyForGenericSingleton Instance
  96.  
  97.     {
  98.  
  99.         get
  100.  
  101.         {
  102.  
  103.             if (!Initialised)
  104.  
  105.             {
  106.  
  107.                 Init(new ReadyForGenericSingleton());
  108.  
  109.             }
  110.  
  111.  
  112.  
  113.             return UniqueInstance;
  114.  
  115.         }
  116.  
  117.     }
  118.  
  119.  
  120.  
  121.     private ReadyForGenericSingleton() { }
  122.  
  123. }
Mar 11 '09 #11
vekipeki
229 Recognized Expert New Member
As I said, that example doesn't help you a lot.

Because this code:

Expand|Select|Wrap|Line Numbers
  1. public sealed class ReadyForGenericSingleton : AbstractGenericSingleton<ReadyForGenericSingleton>
  2. {
  3.     public static ReadyForGenericSingleton Instance
  4.     {
  5.         get
  6.         {
  7.             if (!Initialised)
  8.             {
  9.                 Init(new ReadyForGenericSingleton());
  10.             }
  11.             return UniqueInstance;
  12.         }
  13.     }
  14.  
  15.     private ReadyForGenericSingleton() { }
  16. }
...is not much smaller than this code:

Expand|Select|Wrap|Line Numbers
  1. public sealed class ReadyForGenericSingleton
  2. {
  3.     private static ReadyForGenericSingleton _instance
  4.        = new ReadyForGenericSingleton();
  5.     public static ReadyForGenericSingleton Instance
  6.     {
  7.         get
  8.         {
  9.             return _instance;
  10.         }
  11.     }
  12.  
  13.     private ReadyForGenericSingleton() { }
  14. }
If you use the last example (reflection), you don't need to write anything in your actual class.
Mar 11 '09 #12
kkris1983
8 New Member
I did use reflection code :) Thanks
Mar 11 '09 #13

Sign in to post your reply or Sign up for a free account.

Similar topics

3
2304
by: SimonH | last post by:
Hi all, I would like to make a generic set of methods that could be called regardless of the database behind the scenes. One of the methods I would like would take a string sql statement and an array of DataParameter objects. The problem i have is there doesnt seem to be a generic DataParameter class that I can instantiate. There only...
13
4238
by: Stephen Walch | last post by:
Error C2392 is hitting me hard! I have a managed C++ library that implements a bunch of fixed interfaces. For example, one interface is: public abstract interface IDbCommand { public abstract new System.Data.IDbConnection Connection }
1
1608
by: Dave Booker | last post by:
Is there any way to change the return types on a member function in derived classes? E.g., something like: public abstract class A { protected abstract Object f(); } public abstract class B<T> : A {
8
1817
by: JAL | last post by:
Here is my first attempt at a deterministic collection using Generics, apologies for C#. I will try to convert to C++/cli. using System; using System.Collections.Generic; using System.Text; namespace DeterminedGenericCollection { // I got tired of copy and pasting IDisposable
2
1755
by: dcew | last post by:
Here's what I'm trying to understand; how can you store a generic collection in a variable/field? If I have an abstract generic collection class as follows... public abstract class BizCollection<T> : Collection<T> where T : BizBase { // Collection Implementation override void InsertItem(int index, T item)
25
2996
by: Lars | last post by:
Hi, I have a base class holding a generic list that needs to be accessed by both the base class and its subclasses. What is the best solution to this? I am fairly new to generics, but I am aware of that fact that if you have a class B, that inherits from A, then List<Bdoes NOT inherit from List<A>. So I understand why the example below...
3
1745
by: Otis Mukinfus | last post by:
I've been wrestling with this for a while and can't figure it out. I have a generic method with the following signature: //this compiles OK public abstract class DataMethod { public abstract T Select<T>(); }
1
4426
by: =?Utf-8?B?V2hpdG5leSBLZXc=?= | last post by:
Hi there, I have the following class hierarchy that isn't compiling correctly, and I don't understand why: public abstract class A<Twhere T : System.IComparable<T{ } public abstract class B : System.IComparable<B> { public abstract int CompareTo(B other); }
2
1529
by: Tony | last post by:
Hello! I have some classes below. I have also a generic collection class with this class header definition. public class Farm<T: IEnumerable<Twhere T : Animal {...} Now to my question according to a book that I read it says: "The type of this list is determined by the type parameter T that is passed to Farm<Tand is constraned to be or...
0
7276
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7182
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
1
7142
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7548
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
1
5110
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
4773
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3267
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3259
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1624
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.