[.net] Generics in c#

Started by
7 comments, last by RIGHT_THEN 16 years, 1 month ago
GentleMen, I am unabe to pass a structure into a generic function the error is "cannot be inferred from the usage. Try specifying the type arguments explicitly." This is what i did


        public struct Gen1Test<TP,TP1,TP2,TP3>  
        {
            public TP  S1 ;
            public TP1 S2 ;
            public TP2 S3 ;
            public TP3 S4 ;
        }
        public struct Gen1Test1
        {
            public int S1;
            public int S2;
            public int S3;
            public int S4;
        }


private void SomeFunc_event( object sender, EventArgs e )
        {



            
            Gen1Test<string, string, string, string> x1 = new Gen1Test<string, string, string, string>(); //alright works fine

            Gen1Test<string, string, string, Gen1Test1> x = new Gen1Test<string, string, string, Gen1Test1>(); 

/* i was testing if a  structure can be passed to a generic function
And if A Generic Structure takes Another Structure of its own kind
or other kind it does not!!!
*/


            string S2= "hello" ;
            
            x.S1 = "1";
            x.S2 = S2;
            x.S3 = S2 + "1";
            x.S4.S1 = 50 ;
            x.S4.S1 = 51;
            x.S4.S1 = 52;
            x.S4.S1 = 53;

            CheckGent1Test( x)  ; 

//            CheckGent1Test<this is have tired too>( x)  ; 



        }

        
//this function works if i dont Pass struct in struct Gen1Test Parameters
        private void CheckGent1Test<TP>( Gen1Test<TP,TP,TP,TP> x)
        {
            MessageBox.Show( x.S1.GetType().ToString() +" <-> " +  x.S1.ToString()+ "\n"+
                             x.S2.GetType().ToString() +" <-> " +  x.S2.ToString()+ "\n"+
                             x.S3.GetType().ToString() +" <-> " +  x.S3.ToString()+ "\n"+
                             x.S4.GetType().ToString() +" <-> " +  x.S4.ToString()
            ) ;    
        
        }


Thankyou
RIGHT_THEN


[\source]
Advertisement
Please specify the exact line where the error is being thrown?

And might I suggest you make the names of your structs, variables, and methods clearer and more distinct? It's hard to make heads or tails of what you're trying to do there.
The line
CheckGent1Test( x );

won't work because
private void CheckGent1Test<TP>( Gen1Test<TP, TP, TP, TP> x )

means all type parameters for its argument's type must be the same. However, x has type Gen1Test<string, string, string, Gen1Test1>.
If you want CheckGen1Test to work on x, redefine it as
private void CheckGent1Test<T1,T2,T3,T4>( Gen1Test<T1,T2,T3,T4> x )
Sir Mr. SamLowry

Thankyou VeryMuch For your Reply It Worked
But a New Problem Arose.
Here it is

I thought As with events one is Object parameter
and another is EventSpecific Parameter
Like (Object Sender, Event e);

I would make use of generics but problem
arose
With the Event Functions When we know the Sender
object We merly typecast it
[source lang=c#]((ObjectThatHasRaisedThisEvent)Sender).  |-------------|                                         |Properties   |                                          |Of Object    |                                         |Pop Up In    |                                         |This Window  |                                         |_____________|I Thought The Same would Happen With GenericsBut With Generics Compiler Refuses To Change TypeCast Like ThatFor Instancepublic Struct GenericStruct1<Tp,Tp1,Tp2,Tp3>{   public Tp  TpVar  ;   public Tp1 Tp1Var ;   public Tp2 Tp2Var ;   public Tp3 Tp3Var ;}public Struct GenericStruct2<Tp,Tp1,Tp2,Tp3>{   public Tp  TpVar  ;   public Tp1 Tp1Var ;   public Tp2 Tp2Var ;   public Tp3 Tp3Var ;}public void Func1(){// making variable GenericStruct1<string, string, string, GenericStruct2<int, int, int, int>> x = new   GenericStruct1<string, string, string, GenericStruct2<int, int, int, int>>();            string S2 = "Hello" ;                        x.TpVar  = "1"      ; //because it is a string passing string value            x.Tp1Var = S2       ;  // it is string too            x.Tp2Var = S2 + "1" ; // joining To Strings //caution:- i dont know why PLUS sign i wrote above is not visible in joining            x.Tp3Var.TpVar = 51;   // This Parameter is Struct Itself And its 1st Member i want as an int so 51            x.Tp3Var.TpVar1 = 52; // int            x.Tp3Var.TpVar2 = 53; // int            x.Tp3Var.TpVar3 = 54; // int/*I want to see all these values in another functionSo i pass it to function Like this*/Func1(ref x); // it works fine}public void Func1<Tp,Tp1,Tp2,Tp3>( ref GenericStruct1<Tp, Tp1, Tp2, Tp3> x ){//      I thought here i can see all the values like thisMessageBox.Show( x.TpVar.GetType().ToString() + " <-> " + x.TpVar.ToString() + "\n" +                             x.Tp1Var.GetType().ToString() + " <-> " + x.Tp1Var.ToString() + "\n" +                             x.Tp2Var.GetType().ToString() + " <-> " + x.Tp2Var.ToString() + "\n" +                             x.Tp3Var.GetType().ToString() + " <-> " + x.Tp3Var.ToString() + "\n" //+ "\n" +);             // and it all works well to this point The last line in MessageBox// statement x.Tp3Var.GetType().ToString() + " <-> " + x.Tp3Var.ToString() // shows The Type as GenericStruct2<Tp, Tp1, Tp2, Tp3>>// Fine But how do i see the values inside this GenericStruct2 Passed here// i tried following things1) string Str1 = ((GenericStruct2<Tp, Tp1, Tp2, Tp3>>)x.TpVar3).TpVar.ToString() ; // it says while compiling Cannot Convert Tp3 to GenericStruct2 Type2) string Str1 = ((GenericStruct2<int, int, int, int>>)x.TpVar3).TpVar.ToString() ; // //Same Error As Above3) string Str1 = ((int)x.TpVar3).TpVar.ToString() ; // same error4) i tried FieldInfo[] FInfo = x.TpVar3.GetType().GetFields(); //okay It does//get correctly all the fields four of them and states they are System.Int32 types But how do i retrieve values inside these fields I dont know the wayPlease Help!!!}GrateFullyRIGHT_THEN

i'm not too sure what you're trying to do , you can't cast your already typed object to a generic , it's normal that

x.Tp3Var.GetType().ToString() + " <-> " + x.Tp3Var.ToString()

doesn't enumerate the contents of tp3var since tp3var in this case is a struct & not an int . you'd need to enumerate each of it's members one by one

x.Tp3Var.TpVar.tostring();

the simplest thing if you just want to enumerate all your members is to override tostring at the class level to build a string of all the values & (if one of the value is gen1test type) enumerate those recursively , but the point of generics isn't to be able to toss any value anywhere , just to know at compile time what type you will have to get string typing , if you're gonna use it to store anything & not do operations restricted on the type you're prolly not making the right choice. if you want something that contains values that can themselves contain value you might as well have a type that manage a list of objects that can themselves be list of objects & parse it recursively enumerating all values
here's an example using tostring override & generics tho for information (the overriden tostring calls tostring on all elements & builds a string for that , it's recursive in that , if the object it calls tostring on is a gentype struct (like the arg4 of the 1st struct in my case it will call it's tostring too wich will return a string built from all elements)

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace generics{    class Program    {        static void Main(string[] args)        {            GenType<int, int, int, GenType<int, int, int, string>> test = new GenType<int, int, int, GenType<int, int, int, string>>(50, 20, 13, new GenType<int, int, int, string>(44, 84, 65, "test"));            Console.WriteLine(test.ToString());        }    }    public class GenType<T1,T2,T3,T4>    {        public GenType(T1 a1, T2 a2, T3 a3, T4 a4)        {            arg1 = a1;            arg2 = a2;            arg3 = a3;            arg4 = a4;        }        T1 arg1;        T2 arg2;        T3 arg3;        T4 arg4;        public override string ToString()        {            string s = arg1.ToString() + " " + arg2.ToString() + " " + arg3.ToString() + " " + arg4.ToString();            return s;        }    }}


this returns 50 20 13 44 84 65 test as expected
Sir Mr. RanaKor,

Thanks for your reply
1) First Thing Which you Said That
   "I dont Understand What you are trying to do"Well at this point i am merely testing it and notputting any logic to it.I was trying to make a class libraryfor myself in which i would put my frequently used Functionality.In them are some functions which i have to write again only for themto handle different Types allthou inside logic is the sameI tried getting the same function to work with all using Objectbut it does not.so i thought let me try templates. which i found arecalled generics in c#.So i said let me see how it works in c# so i placed all Thatis above in a class to test it out how it works.i am not using ToString() because i want string Representationin the end or  that is what i want to do . i Used ToString()Merely because i wanted to see the values passed in the MessageBox.And see if i can Use Generics like that or not.


2) Second Thing You Said
"but the point of generics isn't to be able to toss any value anywhere , just to know at compile time what type you will have to get string typing  if you're gonna use it to store anything & not do  operations restricted on the type you're prolly not making the right choice"Yes You Got Me by the Neck HereThat is exactly what i want to do in the end Toss Any Value Anywhere.But not to Get the Type During Runtime And Get It Printed As String.But to Know Its type And Do The Needful According To the Type Recieved.

3)Third Thing You Said
"x.Tp3Var.GetType().ToString() + " <-> " + x.Tp3Var.ToString()doesn't enumerate the contents of tp3var since tp3var in this case is a struct & not an int . you'd need to enumerate each of it's members one byone x.Tp3Var.TpVar.tostring();"Your Opinion Is Correct (Which Has To be) !!!But i am not trying to enumerate it there in that statement I just Gotit Tell Its type twice."x.Tp3Var.TpVar.ToString() is what i should do to enumerate it"Excatly is what i tried to do But Intellisense Wont Recognize Anything Beyound x.Tp3Var I tried Putting aDot after it Like this x.Tp3Var.|----------|                                | nothing  |                                | Appeared |                                | Here     |                                |__________|But Did Write That Statement On My own x.Tp3Var.TpVar.ToString();Complier Gave Error That is does not recognise it.If it would hve recognised I wont have posted this post.


So My Question Still Stands How do i Get To Know What Is
Inside A Generic Parameter And The Value Inside Those
Parameters.I do know how to know the types of generic
Parameters.But i do not know how to get their Values
When the Generic Parameter is a Generic Struct Itself.


It has to work this way for me that
There is a Class Which is not generic
But has a Function in it Which is generic
As i have made in previous posts.
When i will pass Parameter To this Function
It would be a Generic Struct Contiaing Another
Generic Struct as its last Field And i would
Want to use the Values of that Last Field
"Can That Be Done".

Please Help Me Understanding This Phenonenon Aspect
Of Generics.
Do i need to Eleborate more on what i want to do


GrateFully
RIGHT_THEN

[Edited by - RIGHT_THEN on March 10, 2008 2:25:23 AM]
yes it can be done , actually that's just what my code did (cept it returned it in string form) .

could you post the exact thing you're trying to do tho (not something broad , maybe an actual snippet of final use? it still sounds to me you're trying to do something not too obvious where you could do something simpler)

basically you're saying you need to know the values of something of wich you won't know the type of? wich isn't the mindset of generics (make containers for diferent type but use them as a specific type) so it's easier if you try to clarify what you need (not "i need to get something to give me values instead of a generic struct" but the actual need , as in "i made this program to do this & i decided to do it this way for this reason" etc)
Sir Mr. RanaKor,


I have found a Way to Get the Value of a Generic Type
It is like this But the Handicap About it is That
I have to know its Type in Advance to use it in the
End function.

public struct GenericStruct1<Tp,Tp1,Tp2,Tp3>          {            public Tp  TpVar  ;            public Tp1 Tp1Var ;            public Tp2 Tp2Var ;            public Tp3 Tp3Var ;        }private void CheckGent1Test<TP,TP1,TP2,TP3>( ref GenericStruct1<TP, TP1, TP2, TP3> x)        {            MessageBox.Show( x.TpVar.GetType().ToString() + " <-> " + x.TpVar.ToString() + "\n" +                             x.Tp1Var.GetType().ToString() + " <-> " + x.Tp1Var.ToString() + "\n" +                             x.Tp2Var.GetType().ToString() + " <-> " + x.Tp2Var.ToString() + "\n" +                             x.Tp3Var.GetType().ToString() + " <-> " + x.Tp3Var.ToString() + "\n"                                                         ) ;                        Type[] Typ2 = x.GetType().GetGenericArguments();            FieldInfo[] FInfo1 = Typ2[3].GetFields();                         Type Typ123 = x.Tp3Var.GetType();               object Con1 = Convert.ChangeType(x.Tp3Var, Type.GetType(x.Tp3Var.GetType().ToString() ));// if i had not Used GenericStruct2<> here it would not have worked// how to avoid  this            MessageBox.Show (((GenericStruct2<int, int, int, int>)Con1).TpVar.ToString () + "\n" +                             ((GenericStruct2<int, int, int, int>)Con1).Tp1Var.ToString() + "\n" +                             ((GenericStruct2<int, int, int, int>)Con1).Tp2Var.ToString() + "\n" +                             ((GenericStruct2<int, int, int, int>)Con1).Tp3Var.ToString() + "\n" + "Got It" );                         return;}


Next You Asked for a Real Time Code Well Here it is in the
end function Which Redims a Array I would be making it to
Redim a Multidimensional Array but to this point it
is single dimensional I dont know how to test a
Generic Type here Consider A Generic Type for some Array
which a I might Make in future and need to redim it.

public void CallingFunc(){PARAMSReDimPreserveArray<int[]> ReDimPreserveArrayPARAMS = new PARAMSReDimPreserveArray<int[]>(); // this work right i did redim it//PARAMSReDimPreserveArray<GenericStruct1<int, int, int, int>[]> ReDimPreserveArrayPARAMS = new PARAMSReDimPreserveArray<GenericStruct1<int, int, int, int>[]>(); // dont know how would this work so commeted it this is where i need help            GenericStruct1<int, int, int, int>[] Gen1TestArry = new GenericStruct1<int, int, int, int>[5];            Gen1TestArry[0].TpVar  = 1  ;            Gen1TestArry[0].Tp1Var = 2  ;            Gen1TestArry[0].Tp2Var = 3  ;            Gen1TestArry[0].Tp3Var = 4  ;                                    int[] IntArry = { 1,2,13 } ;                        //ReDimPreserveArrayPARAMS.ArrayToResize          = Gen1TestArry  ; // dont know how to use this in end funciton            ReDimPreserveArrayPARAMS.ArrayToResize          = IntArry ; // did it            ReDimPreserveArrayPARAMS.SizeToSet              = 10      ;            ReDimPreserveArrayPARAMS.FunctionStatus         = new FUNCTIONSOPINION()                                    ;            ReDimPreserveArrayPARAMS.ResizingStatus         = new PARAMSReDimPreserveArray<int[]>.ReDimPreserveArray()  ;            //ReDimPreserveArrayPARAMS.ResizingStatus = new PARAMSReDimPreserveArray<Gen1Test<int, int, int, int>[]>.ReDimPreserveArray();                MessageBox.Show("Value In 0th element Before Rediming"+ "\n" + IntArry[0].ToString());             MessageBox.Show("Length Of Array Before Rediming"+ "\n" + IntArry.Length.ToString());             ReDimPreserveArray(ref ReDimPreserveArrayPARAMS);            IntArry = ReDimPreserveArrayPARAMS.ArrayToResize;            MessageBox.Show("Length Of Array After Rediming"+ "\n" +IntArry.Length.ToString ());            MessageBox.Show("Value In 3rd element After Rediming"+ "\n" + IntArry[2].ToString()); // got results correctly            }public enum FUNCTIONSOPINION{            NOTSUCCESSFUL        = 0 ,            SUCCESSFUL           = 1 ,            PARTIALLYSUCCESSFUL  = 2 ,            FAILEDBECAUSEOFERROR = 3 ,            COULDNOT_DO_WHAT_THIS_FUNC_WAS_MADE_FOR   = 0 ,            DID_WHAT_THIS_FUNC_WAS_MADE_FOR           = 1 ,            PARTIALLY_DID_WHAT_THIS_FUNC_WAS_MADE_FOR = 2 ,            None   = -1 ,            IGNORE = -2}public struct PARAMSReDimPreserveArray<T>{    public FUNCTIONSOPINION FunctionStatus   ;        public enum ReDimPreserveArray    {         RECIEVED_ARRAY_VARIABLE_ISNULL      = 0 ,         SIZE_CANNOTBE_ZERO                  = 1 ,         RECIEVED_VARIABLE_IS_NOT_AN_ARRAY   = 2 ,         COULDNOT_DETERMINE_THE_TYPE_OFARRAY = 3 ,         RESIZED                             = 4 ,         COULDNOTRESIZE                      = 5 ,                                    NONE    = -1 ,         IGNORE  = -2    }    public ReDimPreserveArray ResizingStatus ;        public T                  ArrayToResize  ;    public int                SizeToSet      ;} ;public void ReDimPreserveArray<T>( ref PARAMSReDimPreserveArray<T> ThisFuncsPARAMS ){    try    {                bool    IsItArray               = true          ;             Type    TypeOfArrayRecieved                     ;        object  ArrayToResize_Dup1      = new object()  ;                if (ThisFuncsPARAMS.ArrayToResize == null)        {            ThisFuncsPARAMS.FunctionStatus = FUNCTIONSOPINION.COULDNOT_DO_WHAT_THIS_FUNC_WAS_MADE_FOR   ;            ThisFuncsPARAMS.ResizingStatus = PARAMSReDimPreserveArray<T>.ReDimPreserveArray.RECIEVED_ARRAY_VARIABLE_ISNULL ;            return ;                }        IsItArray = ThisFuncsPARAMS.ArrayToResize.GetType().IsArray;        if (IsItArray == false)        {            ThisFuncsPARAMS.FunctionStatus = FUNCTIONSOPINION.COULDNOT_DO_WHAT_THIS_FUNC_WAS_MADE_FOR ;            ThisFuncsPARAMS.ResizingStatus = PARAMSReDimPreserveArray<T>.ReDimPreserveArray.RECIEVED_VARIABLE_IS_NOT_AN_ARRAY ;            return  ;        }        TypeOfArrayRecieved = ThisFuncsPARAMS.ArrayToResize.GetType() ;        if ( TypeOfArrayRecieved == null )        {             ThisFuncsPARAMS.FunctionStatus = FUNCTIONSOPINION.COULDNOT_DO_WHAT_THIS_FUNC_WAS_MADE_FOR ;             ThisFuncsPARAMS.ResizingStatus = PARAMSReDimPreserveArray<T>.ReDimPreserveArray.COULDNOT_DETERMINE_THE_TYPE_OFARRAY ;        }                if (TypeOfArrayRecieved.ToString().Equals("System.Int32[]"))        {            ArrayToResize_Dup1 = Convert.ChangeType(ThisFuncsPARAMS.ArrayToResize, typeof(int[]));            int[] OldTempArray = new int[((int[])ArrayToResize_Dup1).Length] ;            int[] NewTempArray = new int[ThisFuncsPARAMS.SizeToSet]          ;            ((int[])ArrayToResize_Dup1).CopyTo(OldTempArray, 0)     ;                        ArrayToResize_Dup1 = new int[ThisFuncsPARAMS.SizeToSet] ;            OldTempArray.CopyTo((int[])ArrayToResize_Dup1, 0);            ThisFuncsPARAMS.ArrayToResize  = (T)ArrayToResize_Dup1 ;                        ThisFuncsPARAMS.FunctionStatus = FUNCTIONSOPINION.DID_WHAT_THIS_FUNC_WAS_MADE_FOR;            ThisFuncsPARAMS.ResizingStatus = PARAMSReDimPreserveArray<T>.ReDimPreserveArray.RESIZED;                          return;        }                       // Similarly i can redim the known Type but        // How do i check a Generic Type here and Redimit            }    catch (Exception e1)    {        ThisFuncsPARAMS.FunctionStatus = FUNCTIONSOPINION.FAILEDBECAUSEOFERROR;        DealWithErrors.ReportException Re1 = new DealWithErrors.ReportException();        Re1.e1           = e1                   ;        Re1.FileName     = "CommonFunctions"    ;        Re1.FunctionName = "ReDimPreserveArray" ;        DealWithErrors.CommonFunctionsRelatedErrors(ref Re1);    }}


GrateFully
RIGHT_THEN

This topic is closed to new replies.

Advertisement