CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Feb 2008
    Posts
    22

    Generic Collections

    Hi,
    While C# appeared similar to C++ on paper, I have started to struggle learning it. I started off with creating a generic matrix class, but soon simplified the problem to a class doing binary operations.

    Code:
        internal interface IBinaryOperations< T >
        {
            T Add( T val1, T val2 );
            T Subtract( T val1, T val2 );
            T Multiply( T val1, T val2 );
            T Divide( T val1, T val2 );
        }
    
        public class CBinaryOperations< T > : IBinaryOperations< T >
        {
            public static T Add( T val1, T val2 ) {
                return( val1 + val2 ); }
    
            public static T Subtract( T val1, T val2 ) {
                return( val1 - val2 ); }
    
            public static T Multiply( T val1, T val2 ) {
                return( val1 * val2 ); }
    
            public static T Divide( T val1, T val2 ) {
                return( val1 / val2 ); }
        }
    The problem is that it issues the error "CS0019: Operator '+' cannot be applied to operands of type 'T' and 'T'". Could someone please help?
    Thanks
    SB

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

    Re: Generic Collections

    You can't use those maths operators on generic types. It's not supported by the C# specification. You can define the methods like you've done in your interface declaration, but you must implement them for each individal concrete subclass. i.e.

    Code:
    public class IntOperation : IBinaryOperations< int >
    {
        // implement add/subtract etc here
    }
    As you can see, this isn't very pretty.
    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.

  3. #3
    Join Date
    Feb 2008
    Posts
    22

    Re: Generic Collections

    Quote Originally Posted by Mutant_Fruit
    You can't use those maths operators on generic types. It's not supported by the C# specification. You can define the methods like you've done in your interface declaration, but you must implement them for each individal concrete subclass. i.e.

    Code:
    public class IntOperation : IBinaryOperations< int >
    {
        // implement add/subtract etc here
    }
    As you can see, this isn't very pretty.
    But then how can I combine them to get something like:

    Code:
    class CMatrix< T >
    {
            private int _m;
            private int _n;
            private double[,] _data;
    
            public CMatrix< T > Add( ref CMatrix< T > M1, ref CMatrix< T > M2 )
            {
                for( int i = 0; i < _m; i++ )
                {
                    for( int j = 0; j < _n; j++ )
                    {
                        _data[ i, j ] = M1._data[ i, j ] + M2._data[ i, j ];
                    }
                }
                return( this );
            }
    }
    Do you mean the only way possible is to have a separate CMatrix for each data type? Isn't this a step backwards when compared to C++?
    Thanks
    SB

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

    Re: Generic Collections

    Quote Originally Posted by S__B
    But then how can I combine them to get something like:

    Code:
    class CMatrix< T >
    {
            private int _m;
            private int _n;
            private double[,] _data;
    
            public CMatrix< T > Add( ref CMatrix< T > M1, ref CMatrix< T > M2 )
            {
                for( int i = 0; i < _m; i++ )
                {
                    for( int j = 0; j < _n; j++ )
                    {
                        _data[ i, j ] = M1._data[ i, j ] + M2._data[ i, j ];
                    }
                }
                return( this );
            }
    }
    You can't.

    Do you mean the only way possible is to have a separate CMatrix for each data type? Isn't this a step backwards when compared to C++?
    Thanks
    SB
    Thing is, generics aren't quite as broad as they templates are in C++. This is one of the things you just cannot do cleanly with generics.
    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.

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

    Re: Generic Collections

    It is impossible in the way you did, but maybe you are able to do some constraints using 'where' for examle mybe you restrict T to be a valueType or you restrict it to be inherited from a specific class. Maybe especially if you restrict it to be a valueType you will be able to do what you want.
    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

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

    Re: Generic Collections

    Whats about the following

    Code:
    using System;
    using System.Collections.Generic;
    using System.Text;
    namespace GenericConstraints {
    	class Program {
    		static void Main(string[] args) {
    			Matrix<MyInt> a = new Matrix<MyInt>(2, 3);
    			Matrix<MyInt> b = new Matrix<MyInt>(2, 3);
    			b[0, 0] = new MyInt(1);
    			b[0, 1] = new MyInt(5);
    			b[0, 2] = new MyInt(7);
    			b[1, 0] = new MyInt(13);
    			b[1, 1] = new MyInt(41);
    			b[1, 2] = new MyInt(8);
    			Matrix<MyInt> c = new Matrix<MyInt>(2, 3);
    			c[0, 0] = new MyInt(16);
    			c[0, 1] = new MyInt(9);
    			c[0, 2] = new MyInt(13);
    			c[1, 0] = new MyInt(41);
    			c[1, 1] = new MyInt(23);
    			c[1, 2] = new MyInt(11);
    			a.Add(b, c);
    			Console.WriteLine("b[0/0] {0} b[0/1] {1} b[0/2] {2} ", b[0, 0].ToString(), b[0, 1].ToString(), b[0, 2].ToString());
    			Console.WriteLine("c[0/0] {0} c[0/1] {1} c[0/2] {2} ", c[0, 0].ToString(), c[0, 1].ToString(), c[0, 2].ToString());
    			Console.WriteLine("a[0/0] {0} a[0/1] {1} a[0/2] {2} ", a[0, 0].ToString(), a[0, 1].ToString(), a[0, 2].ToString());
     
    			Console.WriteLine("b[1/0] {0} b[1/1] {1} b[1/2] {2} ", b[1, 0].ToString(), b[1, 1].ToString(), b[1, 2].ToString());
    			Console.WriteLine("c[1/0] {0} c[1/1] {1} c[1/2] {2} ", c[1, 0].ToString(), c[1, 1].ToString(), c[1, 2].ToString());
    			Console.WriteLine("a[1/0] {0} a[1/1] {1} a[1/2] {2} ", a[1, 0].ToString(), a[1, 1].ToString(), a[1, 2].ToString());
    	   //********************************************************************************************************************
    			Matrix<MyDouble> f = new Matrix<MyDouble>(2, 3);
    			Matrix<MyDouble> d = new Matrix<MyDouble>(2, 3);
    			d[0, 0] = new MyDouble(1.5);
    			d[0, 1] = new MyDouble(13.3);
    			d[0, 2] = new MyDouble(7.2);
    			d[1, 0] = new MyDouble(6.66);
    			d[1, 1] = new MyDouble(4.25);
    			d[1, 2] = new MyDouble(8.18);
    			Matrix<MyDouble> e = new Matrix<MyDouble>(2, 3);
    			e[0, 0] = new MyDouble(23.12);
    			e[0, 1] = new MyDouble(46.37);
    			e[0, 2] = new MyDouble(10.1);
    			e[1, 0] = new MyDouble(74.89);
    			e[1, 1] = new MyDouble(3.0);
    			e[1, 2] = new MyDouble(11.11);
    			f.Add(d, e);
    			Console.WriteLine("d[0/0] {0} d[0/1] {1} d[0/2] {2} ", d[0, 0].ToString(), d[0, 1].ToString(), d[0, 2].ToString());
    			Console.WriteLine("e[0/0] {0} e[0/1] {1} e[0/2] {2} ", e[0, 0].ToString(), e[0, 1].ToString(), e[0, 2].ToString());
    			Console.WriteLine("f[0/0] {0} f[0/1] {1} f[0/2] {2} ", f[0, 0].ToString(), f[0, 1].ToString(), f[0, 2].ToString());
    			Console.WriteLine("d[1/0] {0} d[1/1] {1} d[1/2] {2} ", d[1, 0].ToString(), d[1, 1].ToString(), d[1, 2].ToString());
    			Console.WriteLine("e[1/0] {0} e[1/1] {1} e[1/2] {2} ", e[1, 0].ToString(), e[1, 1].ToString(), e[1, 2].ToString());
    			Console.WriteLine("f[1/0] {0} f[1/1] {1} f[1/2] {2} ", f[1, 0].ToString(), f[1, 1].ToString(), f[1, 2].ToString());
    		}
    	}
    	public interface IMyParams<T> {
    		void Add(T b, T c);
    		string ToString();
    	}
    	public class Matrix<T> where T : IMyParams<T>  , new()
    	{
    		private int _m;
    		private int _n;
    		public  T[] _data;
    		private T _result;
    		public Matrix(int m, int n) {
    			_m = m;
    			_n = n;
    			_data = new T[_m * _n];
    		}
    		public T this[int i, int j] {
    			get {
    				return _data[i * _n + j];
    			}
    			set {
    				_data[i * _n + j] = value;
    			}
    		}
    		public Matrix<T> Add( Matrix<T>  val1, Matrix<T>  val2) {
    			
    			for (int i = 0; i < _m; i++) {
    				for (int j = 0; j < _n; j++) {
    					_result = new T();
    					_result.Add(val1[i, j], val2[i, j]);
    					_data[i * _n + j] = _result;
    				}
    			}
    			return this;
    		}
    	}
    	public class MyInt : IMyParams<MyInt>{
    		private int _a;
    		// Ctors
    		public MyInt() { }
    		public MyInt(int a) {
    			_a = a;
    		}
    		// IParams
    		public virtual void Add(MyInt b, MyInt c) {
    			_a = b._a + c._a;
    		}
    		public override string ToString() {
    			return _a.ToString();
    		}
    	}
    	public class MyDouble : IMyParams<MyDouble> { 
    		private double _a;
    		// Ctors
    		public MyDouble() { }
    		public MyDouble(double a) {
    			_a = a;
    		}
    	// IParams
    		public virtual void  Add(MyDouble b, MyDouble  c) {
    			_a = b._a  + c._a ;
    		}
    		public override string ToString(){
    			return _a.ToString();
    		}
       }
    }
    I did to different values to test it
    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

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