CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Dec 2003
    Posts
    112

    [RESOLVED] Generic Methods without Where

    Suppose I have a class that has a collection. I want to make a generic method to access certain types of objects within that collection. Basically what I want is:

    Code:
    class MyCollection
    {
      List<MyObject> storedObjects;
    
      public T GetFirstObjectOfType<T>()
      {
    
        foreach(MyObject obj in storedObjects)
        {
           if(obj is T)
              return (T) obj;
        }
    
        return null;
      }
    }
    That is what I would like. The problem is when I try to compile it gives me an error:

    Cannot convert type MyObject to 'T'

    How can I get around this. I know that if I change it to:

    Code:
    public T GetFirstObjectOfType<T>() where T : MyObject
    It will work, but now I am limited in the types that I can search for. For example if I want to search for an object that implements a specific interface I can't because that interface is not of type MyObject.

    So for example if I wanted to do something like:

    Code:
    IDisposable disposableObject = collection.GetFirstObjectOfType<IDisposable>();
    This won't work because IDisposable does not inherit MyObject.
    Eggman
    Using: VS 2008 w. Net 3.5

  2. #2
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Generic Methods without Where

    A class or OBJECT constraint should be sufficient (I would have to test to confirm)
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  3. #3
    Join Date
    Dec 2003
    Posts
    112

    Re: Generic Methods without Where

    Quote Originally Posted by TheCPUWizard
    A class or OBJECT constraint should be sufficient (I would have to test to confirm)
    Not sure what you mean by that. Can you elaborate?
    Eggman
    Using: VS 2008 w. Net 3.5

  4. #4
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Generic Methods without Where

    Quote Originally Posted by Eggman002
    Not sure what you mean by that. Can you elaborate?
    Actually T MUST be derived from MyObject or the element could not be in the list in the first place....

    But what I meant for a more general case:

    Code:
    T Get<T>()
    where  T : class
    {
       return (T) something;
    }
    or
    Code:
    T Get<T>()
    where  T : Object
    {
       return (T) something;
    }
    As I said, either a "class" or an "Object" constraint....
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  5. #5
    Join Date
    Dec 2003
    Posts
    112

    Re: Generic Methods without Where

    Quote Originally Posted by TheCPUWizard
    Actually T MUST be derived from MyObject or the element could not be in the list in the first place....
    No it doesn't have to be derived from MyObject. Certainly the objects in the list have to be derived from MyObject, but T could be anything.

    So I might have:

    Code:
    class MyComparableObject : MyObject, IComparable
    {
    }
    Then I might want to do:

    Code:
    IComparable comparableObject = collection.GetFirstObjectOfType<IComparable>();
    So in this case, the collection can contain instances of MyComparableObject because they are derived from MyObject. No problem. However I am not interested in instances of MyObject or MyComparableObject , I am interested in any and all objects that implement IComparable which happen to include MyComparableObject.

    So using:

    Code:
    public T GetFirstObjectOfType<T>() where T : MyObject
    Won't work because IComparable is not derived from MyObject. Sure I could do:

    Code:
    IComparable comparableObject = collection.GetFirstObjectOfType<MyComparableObject>();
    But again, that is not necessarily what I am looking for. I want IComparable.

    Also using "where T : class" or "where T : Object" don't work. Actually where T : Object won't even compile because Object is a special class.
    Eggman
    Using: VS 2008 w. Net 3.5

  6. #6
    Join Date
    Mar 2005
    Location
    Vienna, Austria
    Posts
    4,538

    Re: Generic Methods without Where

    Hi !

    Whats about this one
    Code:
    public class MyCollection {
    	List<object> storedObjects;
    	public T GetFirstObjectOfType<T>() where T:class{
    		foreach (object obj in storedObjects) {
    			T test = obj as T;
    			 if (test != null){
    				return test;
    			 }
    		}
    		return null;
    	}
    }
    This compiles (tested ) and shoul work IMHO
    Last edited by JonnyPoet; October 28th, 2008 at 05:19 PM.
    Jonny Poet

    To be Alive is depending on the willingsness to help others and also to permit others to help you. So lets be alive. !
    Using Code Tags makes the difference: Code is easier to read, so its easier to help. Do it like this: [CODE] Put Your Code here [/code]
    If anyone felt he has got help, show it in rating the post.
    Also dont forget to set a post which is fully answered to 'resolved'. For more details look to FAQ's about Forum Usage. BTW I'm using Framework 3.5 and you ?
    My latest articles :
    Creating a Dockable Panel-Controlmanager Using C#, Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7

  7. #7
    Join Date
    Mar 2005
    Location
    Vienna, Austria
    Posts
    4,538

    Re: Generic Methods without Where

    Here is the full test Console Application
    Code:
    namespace ConsoleApplication1 {
    	class Program {
     
    		static void Main(string[] args) {
    		MyCollection coll = new MyCollection();
    			coll.Add(new A());
    			coll.Add(new D());
    			coll.Add(new C());
    			coll.Add(new B());
    			IMyInterface firstOne = coll.GetFirstObjectOfType<IMyInterface>();
    			Console.WriteLine("first One {0}", firstOne.GetName()); 
     
    		}
     
    	}
    	public class MyCollection {
    		List<object> storedObjects;
     
    		public MyCollection() {
    			storedObjects = new List<object>();
    		}
     
    		public T GetFirstObjectOfType<T>() where T:class{
     
    			foreach (object obj in storedObjects) {
    				T test = obj as T;
    				 if (test != null){
    					return test;
    				 }
    			}
     
    			return null;
    		}
     
    		public void Add(object x){
    			storedObjects.Add(x);
    		}
    	}
     
    	public class A { 
    	 private string _name;
    		public A(){
    		 _name = "A";
    		}
    		public string GetName(){
    		 return _name;
    	 } 
    	}
     
    	public class B:IMyInterface {
    	 private string _name;
    		public B(){
    		 _name = "B";
    		}
    	#region IMyInterface Member
    	 public string GetName(){
    		 return _name;
    	 }
    	#endregion	
    	}
    	public class C { 
    	 private string _name;
    		public C(){
    		 _name = "C";
    		}		public string GetName(){
    		 return _name;
    	 } 
    	}
    	public class D :IMyInterface{ 
    	 private string _name;
    		public D(){
    		 _name = "D";
    		} 
    	#region IMyInterface Member
    	 public string GetName(){
    		 return _name;
    	 }
    	#endregion
    	}
     
    	public interface IMyInterface{
    	 string GetName();
    	}
    }
    Tested - works
    As you can see I created four simple similar classes. The difference is: only two of them containing the interface. The others have the same mathod, but it is not defined as to have the interface.
    The result is that class 'D' is the first one in the list which is containing the interface. When I change the order in which I added the casses it always gives correct result.

    I generally have used object instead of MyObject because MyObject itself restricts the objects you can store in your list as they need to derive from MyObject then.
    Last edited by JonnyPoet; October 28th, 2008 at 05:19 PM.
    Jonny Poet

    To be Alive is depending on the willingsness to help others and also to permit others to help you. So lets be alive. !
    Using Code Tags makes the difference: Code is easier to read, so its easier to help. Do it like this: [CODE] Put Your Code here [/code]
    If anyone felt he has got help, show it in rating the post.
    Also dont forget to set a post which is fully answered to 'resolved'. For more details look to FAQ's about Forum Usage. BTW I'm using Framework 3.5 and you ?
    My latest articles :
    Creating a Dockable Panel-Controlmanager Using C#, Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7

  8. #8
    Join Date
    May 2007
    Posts
    1,546

    Re: Generic Methods without Where

    Code:
        class MyCollection
        {
            List<MyObject> storedObjects;
    
            public T GetFirstObjectOfType<T>()
            {
    
                foreach (MyObject obj in storedObjects)
                {
                    if (obj is T)
                        return (T)(object)obj;
                }
    
                return default(T);
            }
        }
    Just cast 'obj' to object before casting to 'T'.

    If you don't add a generic constraint to the declaration which disallows value types, you'll have to change the 'return null' to 'return default(T)'.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  9. #9
    Join Date
    Dec 2003
    Posts
    112

    Re: Generic Methods without Where

    Quote Originally Posted by Mutant_Fruit
    Just cast 'obj' to object before casting to 'T'.
    Brilliant. That was the trick. I am pretty sure that is why JonnyPoet's solution also worked because he was storing a list of objects rather than MyObject. But the casting to Object first does the trick and works perfectly for my situation (where switching the list to store objects is not acceptable).

    Thanks.
    Eggman
    Using: VS 2008 w. Net 3.5

  10. #10
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Generic Methods without Where

    Quote Originally Posted by Eggman002
    Brilliant. That was the trick. I am pretty sure that is why JonnyPoet's solution also worked because he was storing a list of objects rather than MyObject. But the casting to Object first does the trick and works perfectly for my situation (where switching the list to store objects is not acceptable).

    Thanks.
    Glad you have a solution. I did just want to point out that:
    Code:
    X is Y;
    ;
    if internally implemented along the line of
    Code:
    if (X == null)
      return null;
    Z tmp = X as Y;
    if (tmp == null)
       throw .....;
    return tmp;
    The point being is thart casting take significant overhead (unlike C++ where it is just a compiler feature, the runtime has to completely walk the meta data even for an explicit "hard" cast.

    As a result the "IS" statement should typically only be used IF the result of the cast is NOT going to be used.

    Have you tried???
    Code:
          T tmp = obj as T;
          if (tmp != null)
             return tmp;
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  11. #11
    Join Date
    Mar 2005
    Location
    Vienna, Austria
    Posts
    4,538

    Re: Generic Methods without Where

    Quote Originally Posted by TheCPUWizard
    ...
    Have you tried???
    Code:
    T tmp = obj as T;
    if (tmp != null)
    return tmp;
    Wiz yea, this is exactly what I suggested.Look in my two post I did before.
    Eggmann002 To make it totally clear: It works even if you use Myobject look here
    Code:
    public T GetFirstObjectOfType<T>() where T: class{
    foreach (MyObject obj in storedObjects) {
    	 T test = obj as T;
    	 if (test != null) {
    			return test;
    	 }
    	}
    	return null;
    }
    . The full example so you will see, it works is attached in the zip. I only had to derive all my example classes A,B,C,D from MyObject. The example only needs to restrict T to be a class, nothing else and that was told from WizBang also in one of the earlier posts. And because I got the idea, you didn't get him, I did a short example for you.
    Attached Files Attached Files
    Last edited by JonnyPoet; October 29th, 2008 at 01:58 PM.
    Jonny Poet

    To be Alive is depending on the willingsness to help others and also to permit others to help you. So lets be alive. !
    Using Code Tags makes the difference: Code is easier to read, so its easier to help. Do it like this: [CODE] Put Your Code here [/code]
    If anyone felt he has got help, show it in rating the post.
    Also dont forget to set a post which is fully answered to 'resolved'. For more details look to FAQ's about Forum Usage. BTW I'm using Framework 3.5 and you ?
    My latest articles :
    Creating a Dockable Panel-Controlmanager Using C#, Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 | Part 7

  12. #12
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Generic Methods without Where

    Quote Originally Posted by JonnyPoet
    Wiz yea, this is exactly what I suggested.Look in my two post I did before.
    I know you did.

    I was just adding that it is a faster solution than the hard cast(s) after using "IS".....
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured