Click here to Skip to main content
15,867,568 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Dear all
I’m a beginner in c# and I’m fighting with the following.

I try to design a generic class, in which a method should assign a value to a parameter. For basic data types it is easy with a ref or out parameter. But I like to pass a property from another class which defines the get/set method.

The problem is, I do not have any idea whether it is possible and if yes how to do it :(

Thank you in advance.
Regards


Code fragments:

a.) The Generic class
C#
public class MyGeneric<TWhatever, TResult>
{
  //
  // ******Here you find my problem******
  //
  // This method should assign the result to a property of another class
  public bool TryDoAnything(???here I like to pass "MyAny.AnyData" to assign
                            data as parameter result???)
  {
    ...
    if (success)
    {
      // In real the result comes from TWhatever
      result= new TResult();
    }
    return(success);
  }
}


b.) In the application
C#
{
  MyGeneric<TheWhatever, PropertyClass> myGenericInUse= 
    new MyGeneric<TheWhatever, PropertyClass>();

  MainClass myMain= new MainClass();
  
  ...
  ...
  
  //
  // ******Here probably a have the next problem******
  //
  if (myGenericInUse.TryDoAnything(myMain.PropData))
  {
    // Do what is needed
  }
}


c.) The class with the property which has to be set by the generic class
C#
public class MainClass
{
  private PropertyClass propData;

  public PropertyClass PropData
  {
    get
    {
      return(propData);
    }
    set
    {
      propData= value;
    }
  }
}



d.) The result class (only for completness)
C#
public class PropertyClass
{
}
Posted

You are trying to mix up two unrelated things.

First thing is passing the parameters. You can pass a property as a by-value parameter, because a value is copied from the actual parameter anyway, and a compiler can do it with the property. In contract, out or ref parameter-passing method deal with the reference to the object, which of course cannot be done with the property just because this is not an object at all, this is the method backing the assignment-like syntax.

So, one can pass a property only as a by-value parameter, not out or ref.

By the way, it's a good idea to use a return value instead of out or ref and exceptions instead of Boolean success status. Naerling's advice is very good here. In fact, the success status almost never should be used, and error condition should not be used under any circumstances, as it defeats the purpose of exceptions and makes the code less, much less manageable.

Using generics does not modify a bit in this statement. Generic or non-generic — does not matter, whatsoever.

—SA
 
Share this answer
 
v2
Comments
Sander Rossel 15-Jul-12 0:50am    
I agree that it has nothing to do with Generics. Somehow the OP seemed under the impression that Generics were the problem here, so I showed him that it was not. I sincerely hate a success flag. I've worked on software where a 'SaveToDB' method would go 5 or 6 functions deep and every function returned a success boolean... Unless there are very good reasons not to throw an Exception (and there never is) you should simply throw one if stuff goes awry. It makes life a lot easier :)
Sergey Alexandrovich Kryukov 15-Jul-12 1:06am    
Thank you, Naerling.
The problem is that I did not really understood your statement. When you ask you rhetorical question in the very beginning, it's hard to understand what is your opinion. Maybe I even misunderstood the main points of your post. I think you could state it more clearly, really...
--SA
Sander Rossel 15-Jul-12 0:56am    
By the way, on an entirely unrelated note, have you seen my latest article? It's about IL, Emit and Expression Trees. As I recall you were recently working on a Serializer using IL. I'm curious what you think of it :)
If you're interested you can find it in my articles, it's called "A Look under the hood of the .NET Framework".
Sergey Alexandrovich Kryukov 15-Jul-12 1:03am    
Very interesting topic. I'm working intensively at Reflection.Emit right now, already got very interesting results, but a lot more work lies ahead. Will see it when I have a bit more time (hopefully, on next week), thank you very much for sharing...
--SA
[no name] 15-Jul-12 5:11am    
Thank you Sergey for your comments.
Yes it has nothing to do with generic, it was just my actual situation (and generic only blow up my question).

Never using the success state: How is about int.TryParse and a lot others in .net? It's a similar thing (TryParse) I need to do.

Anyway once again I learned a lot here.

Regards
Why would you not be able to use out or ref when using Generics?
See the following example.
C#
class Program
{
    static void Main(string[] args)
    {
        int i = 10;
        GenericExample<int> ge = new GenericExample<int>();
        Console.WriteLine("The value of i is " + i.ToString());
        ge.SetSomeValue(ref i);
        Console.WriteLine("The value of i is " + i.ToString());
        Console.ReadKey();
    }		
}
    	
public class GenericExample<TResult>
{
    public bool SetSomeValue(ref TResult value)
    {
        value = Activator.CreateInstance<TResult>();
        return true;
    }
}
When running this code in a console application you will see that i is 10 before executing the function and 0 after executing it. You can set i as the value of whatever Property you want.
However, why do you need to return a bool to indicate success? Why not simply return an instance of TResult and throw an Exception if something went wrong (it reduces the amount of if-blocks and allows for proper error handling)?

If you really wanted to set a Property (that is, invoke the set method on a Property and passing the value that was somehow calculated in your method) you could use Reflection, but I don't recommend it. Here is how you would do it.
C#
class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        p.SomeProperty = 24;
        GenericExample<int> ge = new GenericExample<int>();
        Console.WriteLine("The value of SomeProperty is " + p.SomeProperty.ToString());
        ge.SetProperty(p, "SomeProperty");
        Console.WriteLine("The value of SomeProperty is " + p.SomeProperty.ToString());
        Console.ReadKey();
    }		
}

public class Person { public int SomeProperty {get; set;} }

public class GenericExample<TRresult>
{
    public bool SetProperty(object obj, string propertyName)
    {
        System.Reflection.PropertyInfo prop = obj.GetType().GetProperty(propertyName);
        prop.GetSetMethod().Invoke(obj, new object[] {Activator.CreateInstance<TResult>()});
        return true;
    }
}
You can see the downsides to this. If you would change the name of SomeProperty or misspell it you wouldn't get design time support for the error.
 
Share this answer
 
v2
Comments
[no name] 14-Jul-12 11:44am    
Hello Naerling
Thank you very much for your answer and your time.
The difference is, that my generic class needs to assign a value which is a property of other classes and these other classes are not known by the generic class.

Something like:
ge.TryParse(value, otherclass1.A)
ge.TryParse(value, otherclass2.A)

The property “A” is published by these “otherclass1”...using get/set.
Regards
Sander Rossel 14-Jul-12 11:53am    
I was talking about doing something like the following:
int i;
if (ge.SetValue(value, i)) {otherClass.A = i;}

That's probably the best you can do. It has design time type checking, does not incur the performance hit of Reflection and is pretty clear to read.
[no name] 14-Jul-12 11:47am    
Hello Naerling
Just finished reading your second part. That at least is much more nice to read then my solution.
Tanks andregards.
Sander Rossel 14-Jul-12 11:55am    
Take heed that Reflection performs less than 'regular code'. Plus, as I already mentioned, in this case you will lose design time error checking.
See my comment above. It is the preferred method.
Sergey Alexandrovich Kryukov 15-Jul-12 0:23am    
I think you are trying to complicate a very simple problem. First, forget about generics -- it does not matter. The only problem is out and ref parameter passing -- cannot be uses with properties.

It's a good idea to use return value instead ref or out, but ref and out are very useful in certain cases.

Please see my answer.
--SA
I found a way but I do not like it very much.
Regards

a.) The Generic class
C#
public class MyGeneric<TWhatever,TResult>
{

  // Define an event type
  public delegate void PropertyAssign(TResult Value);

  // Pass a delegate (event?) to assign the result
  public bool TryDoAnything(PropertyAssign assignResult)
  {
    ...
    if (success)
    {
      // In real the result comes from TWhatever
      assignResult(new TResult());
    }
    return(success);
  }
}


b.) Use it in the application
C#
{
  MyGeneric<TheWhatever, MainClass> myGenericInUse= new 
    MyGeneric<TheWhatever, MainClass>();

  MainClass myMain= new MainClass();
  
  ...
  ...
  
  //
  // Here how to use it. A lot to write....
  //
  if (myGenericInUse.TryDoAnything(delegate(PropertyClass value)
                                   {myMain.PropData= value;}))
  {
    // Do what is needed
  }
}
 
Share this answer
 
v4
Comments
Sander Rossel 14-Jul-12 11:15am    
I did not understand your question, but now that I see your own proposed solution I think I got it.
I think using an 'out' or 'ref' parameter is bad design 99 out of 100 times. Personally I never needed it.
Anyway, you can still use 'out' or 'ref' when using Generics. See my answer for an example.
[no name] 14-Jul-12 11:33am    
I agree, I also do not like ref and out. But the thing I need to solve is somthing like bool TryParse(value, result).
Regards
Sergey Alexandrovich Kryukov 15-Jul-12 0:24am    
I think you are trying to find a solution for non-existing or artificial problem. First, forget about generics -- it does not matter. The only problem is out and ref parameter passing -- cannot be uses with properties.

It's a good idea to use return value instead ref or out, but ref and out are very useful in certain cases.

Please see my answer.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900