Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Cast Action<T> to Action<object> [modified]

Cast Action<T> to Action<object> [modified]

Scheduled Pinned Locked Moved C#
helptutorial
29 Posts 10 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Adriaan Davel
    wrote on last edited by
    #1

    After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>, can anyone please explain this in small words (I currently have the brain of a 5 year old). There was a poem written along time ago by a person dying with lots of pain, he called it 'Brother Pain', I'm about to write a poem called 'Brother Cannot implicitly convert type 'System.Action<T>' to 'System.Action<object>'' An example:

    public class Base
    {
    public Func<object> OnComplete {get;set;}
    public Base(Func<object> onComplete)
    {
    OnComplete = onComplete;
    }
    }
    public class GenericBase<T> : Base
    {
    public GenericBase(Func<T> onComplete) : base(onComplete) //Error
    {
    OnComplete = onComplete; //Error
    }
    }

    ____________________________________________________________ Be brave little warrior, be VERY brave

    modified on Thursday, March 31, 2011 3:22 AM

    G L P J B 6 Replies Last reply
    0
    • A Adriaan Davel

      After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>, can anyone please explain this in small words (I currently have the brain of a 5 year old). There was a poem written along time ago by a person dying with lots of pain, he called it 'Brother Pain', I'm about to write a poem called 'Brother Cannot implicitly convert type 'System.Action<T>' to 'System.Action<object>'' An example:

      public class Base
      {
      public Func<object> OnComplete {get;set;}
      public Base(Func<object> onComplete)
      {
      OnComplete = onComplete;
      }
      }
      public class GenericBase<T> : Base
      {
      public GenericBase(Func<T> onComplete) : base(onComplete) //Error
      {
      OnComplete = onComplete; //Error
      }
      }

      ____________________________________________________________ Be brave little warrior, be VERY brave

      modified on Thursday, March 31, 2011 3:22 AM

      G Offline
      G Offline
      Groulien
      wrote on last edited by
      #2

      It says 'implicitly', so have you tried an explicit cast?

      public class GenericBase<T> : Base
      {
      public GenericBase(Func<T> onComplete) : base((Func<object>)onComplete) //Added an explicit cast
      {
      OnComplete = (Func<object>)onComplete; //I'm not sure but I believe this is already done by 'base(onComplete)' constructor
      }
      }

      A 1 Reply Last reply
      0
      • A Adriaan Davel

        After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>, can anyone please explain this in small words (I currently have the brain of a 5 year old). There was a poem written along time ago by a person dying with lots of pain, he called it 'Brother Pain', I'm about to write a poem called 'Brother Cannot implicitly convert type 'System.Action<T>' to 'System.Action<object>'' An example:

        public class Base
        {
        public Func<object> OnComplete {get;set;}
        public Base(Func<object> onComplete)
        {
        OnComplete = onComplete;
        }
        }
        public class GenericBase<T> : Base
        {
        public GenericBase(Func<T> onComplete) : base(onComplete) //Error
        {
        OnComplete = onComplete; //Error
        }
        }

        ____________________________________________________________ Be brave little warrior, be VERY brave

        modified on Thursday, March 31, 2011 3:22 AM

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #3

        Adriaan Davel wrote:

        After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>,

        Because T might be an integer, and that's not compatible with object.

        I are Troll :suss:

        A 1 Reply Last reply
        0
        • L Lost User

          Adriaan Davel wrote:

          After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>,

          Because T might be an integer, and that's not compatible with object.

          I are Troll :suss:

          A Offline
          A Offline
          Adriaan Davel
          wrote on last edited by
          #4

          Not sure I understand what you mean, this object x = 1; works...

          ____________________________________________________________ Be brave little warrior, be VERY brave

          W L 2 Replies Last reply
          0
          • A Adriaan Davel

            After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>, can anyone please explain this in small words (I currently have the brain of a 5 year old). There was a poem written along time ago by a person dying with lots of pain, he called it 'Brother Pain', I'm about to write a poem called 'Brother Cannot implicitly convert type 'System.Action<T>' to 'System.Action<object>'' An example:

            public class Base
            {
            public Func<object> OnComplete {get;set;}
            public Base(Func<object> onComplete)
            {
            OnComplete = onComplete;
            }
            }
            public class GenericBase<T> : Base
            {
            public GenericBase(Func<T> onComplete) : base(onComplete) //Error
            {
            OnComplete = onComplete; //Error
            }
            }

            ____________________________________________________________ Be brave little warrior, be VERY brave

            modified on Thursday, March 31, 2011 3:22 AM

            P Offline
            P Offline
            Pete OHanlon
            wrote on last edited by
            #5

            The reason you can't do it is fairly simple. Action<T> is generic - fair enough, and you want it to be Action<object> - ok? Simplistically you would think this would work because no matter what type T was, it would ultimately be convertable to object, as everything derives from object. Suppose though, that type T was a string, and you wanted to use Action<int> - all of a sudden, there's a conversion that is not implicitly possible - in other words, you would have to perform an explicit cast. The cast into object would have to be a special case in the compiler, so they chose not to do this - instead, like for like typing is the only way to achieve this.

            I'm not a stalker, I just know things. Oh by the way, you're out of milk.

            Forgive your enemies - it messes with their heads

            My blog | My articles | MoXAML PowerToys | Onyx

            A 1 Reply Last reply
            0
            • G Groulien

              It says 'implicitly', so have you tried an explicit cast?

              public class GenericBase<T> : Base
              {
              public GenericBase(Func<T> onComplete) : base((Func<object>)onComplete) //Added an explicit cast
              {
              OnComplete = (Func<object>)onComplete; //I'm not sure but I believe this is already done by 'base(onComplete)' constructor
              }
              }

              A Offline
              A Offline
              Adriaan Davel
              wrote on last edited by
              #6

              Did it build on your side? On my side I get 'Cannot convert type 'System.Func<T>' to 'System.Func<object>'' At least now my build error message is different :)

              ____________________________________________________________ Be brave little warrior, be VERY brave

              1 Reply Last reply
              0
              • A Adriaan Davel

                Not sure I understand what you mean, this object x = 1; works...

                ____________________________________________________________ Be brave little warrior, be VERY brave

                W Offline
                W Offline
                Wayne Gaylard
                wrote on last edited by
                #7

                Your example would still be an object, allocated on the heap. To use x as an integer would still need to be converted (int)x = ?

                1 Reply Last reply
                0
                • A Adriaan Davel

                  Not sure I understand what you mean, this object x = 1; works...

                  ____________________________________________________________ Be brave little warrior, be VERY brave

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  Adriaan Davel wrote:

                  this object x = 1; works

                  That wraps your value-type with a reference-type; your number is actually stored in the object, but a number is not an object itself.

                  I are Troll :suss:

                  A P 2 Replies Last reply
                  0
                  • P Pete OHanlon

                    The reason you can't do it is fairly simple. Action<T> is generic - fair enough, and you want it to be Action<object> - ok? Simplistically you would think this would work because no matter what type T was, it would ultimately be convertable to object, as everything derives from object. Suppose though, that type T was a string, and you wanted to use Action<int> - all of a sudden, there's a conversion that is not implicitly possible - in other words, you would have to perform an explicit cast. The cast into object would have to be a special case in the compiler, so they chose not to do this - instead, like for like typing is the only way to achieve this.

                    I'm not a stalker, I just know things. Oh by the way, you're out of milk.

                    Forgive your enemies - it messes with their heads

                    My blog | My articles | MoXAML PowerToys | Onyx

                    A Offline
                    A Offline
                    Adriaan Davel
                    wrote on last edited by
                    #9

                    Thanks for the reply Pete, just not sure I fully understand your explanation. What you are saying that (assuming this was allowed) this wouldn't be a problem:

                    Action<object> act = null;
                    act = new Action<int>();

                    but the problem would come in if I tried:

                    act("a");

                    If that's what you are saying then I'm a bit disappointed in MS because type conversion from object has always posed this challenge (I recon this is why generics was brought in) and yes its fair to expect me to pass the right value in or get a runtime error...

                    ____________________________________________________________ Be brave little warrior, be VERY brave

                    P 1 Reply Last reply
                    0
                    • L Lost User

                      Adriaan Davel wrote:

                      this object x = 1; works

                      That wraps your value-type with a reference-type; your number is actually stored in the object, but a number is not an object itself.

                      I are Troll :suss:

                      A Offline
                      A Offline
                      Adriaan Davel
                      wrote on last edited by
                      #10

                      Ok, but in non-generic syntax this works:

                      private void Button_Click(object sender, RoutedEventArgs e)
                      {
                      Calc(1);
                      }

                      private void Calc(object val)
                      {

                      }

                      but in generic syntax it doesn't?

                      ____________________________________________________________ Be brave little warrior, be VERY brave

                      L 1 Reply Last reply
                      0
                      • A Adriaan Davel

                        Ok, but in non-generic syntax this works:

                        private void Button_Click(object sender, RoutedEventArgs e)
                        {
                        Calc(1);
                        }

                        private void Calc(object val)
                        {

                        }

                        but in generic syntax it doesn't?

                        ____________________________________________________________ Be brave little warrior, be VERY brave

                        L Offline
                        L Offline
                        Lost User
                        wrote on last edited by
                        #11

                        "Shouldn't"; there's a difference between simple types (anything that's a value) and classes, that's why there's a "where T:class" constraint :)

                        I are Troll :suss:

                        A 1 Reply Last reply
                        0
                        • L Lost User

                          "Shouldn't"; there's a difference between simple types (anything that's a value) and classes, that's why there's a "where T:class" constraint :)

                          I are Troll :suss:

                          A Offline
                          A Offline
                          Adriaan Davel
                          wrote on last edited by
                          #12

                          I know that, and object allows me to pass either and respond accordingly inside the method to which I passed the parameter

                          ____________________________________________________________ Be brave little warrior, be VERY brave

                          L 1 Reply Last reply
                          0
                          • A Adriaan Davel

                            I know that, and object allows me to pass either and respond accordingly inside the method to which I passed the parameter

                            ____________________________________________________________ Be brave little warrior, be VERY brave

                            L Offline
                            L Offline
                            Lost User
                            wrote on last edited by
                            #13

                            ..because you can check what type of object that it is. That's what VS does at compile-time, and since an integer isn't an object it gives an error. It could be wrapped in an object, that's true - but if that's what should be done, then it has to be explicit. Remember that you can't inherit from an integer, so it does make sense to differentiate between the parameter-behaviour and the generics' behaviour :)

                            I are Troll :suss:

                            1 Reply Last reply
                            0
                            • A Adriaan Davel

                              Thanks for the reply Pete, just not sure I fully understand your explanation. What you are saying that (assuming this was allowed) this wouldn't be a problem:

                              Action<object> act = null;
                              act = new Action<int>();

                              but the problem would come in if I tried:

                              act("a");

                              If that's what you are saying then I'm a bit disappointed in MS because type conversion from object has always posed this challenge (I recon this is why generics was brought in) and yes its fair to expect me to pass the right value in or get a runtime error...

                              ____________________________________________________________ Be brave little warrior, be VERY brave

                              P Offline
                              P Offline
                              Pete OHanlon
                              wrote on last edited by
                              #14

                              That's exactly what I'm saying. The thing is though, generics were brought in for things like type safety and to prevent aid the developer move away from boxing/unboxing. By having object as the generic type, you've just gone back to having a boxing/unboxing issue - and you're no better off than just passing Action across rather than the generic Action.

                              I'm not a stalker, I just know things. Oh by the way, you're out of milk.

                              Forgive your enemies - it messes with their heads

                              My blog | My articles | MoXAML PowerToys | Onyx

                              A 1 Reply Last reply
                              0
                              • A Adriaan Davel

                                After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>, can anyone please explain this in small words (I currently have the brain of a 5 year old). There was a poem written along time ago by a person dying with lots of pain, he called it 'Brother Pain', I'm about to write a poem called 'Brother Cannot implicitly convert type 'System.Action<T>' to 'System.Action<object>'' An example:

                                public class Base
                                {
                                public Func<object> OnComplete {get;set;}
                                public Base(Func<object> onComplete)
                                {
                                OnComplete = onComplete;
                                }
                                }
                                public class GenericBase<T> : Base
                                {
                                public GenericBase(Func<T> onComplete) : base(onComplete) //Error
                                {
                                OnComplete = onComplete; //Error
                                }
                                }

                                ____________________________________________________________ Be brave little warrior, be VERY brave

                                modified on Thursday, March 31, 2011 3:22 AM

                                J Offline
                                J Offline
                                J4amieC
                                wrote on last edited by
                                #15

                                Why not just to the following, from what I could see would give youthe exact same result, with the benefit of actually compiling!

                                public interface IBase
                                {
                                Func OnComplete { get; set; }
                                }

                                public class Base : IBase
                                {

                                public Base(Func onComplete)
                                {
                                    OnComplete = onComplete;
                                }
                                
                                public Func OnComplete { get; set; }
                                

                                }
                                public class GenericBase : IBase
                                {
                                public GenericBase(Func onComplete)
                                {
                                OnComplete = onComplete;
                                }

                                public Func OnComplete { get; set; }
                                

                                }

                                1 Reply Last reply
                                0
                                • A Adriaan Davel

                                  After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>, can anyone please explain this in small words (I currently have the brain of a 5 year old). There was a poem written along time ago by a person dying with lots of pain, he called it 'Brother Pain', I'm about to write a poem called 'Brother Cannot implicitly convert type 'System.Action<T>' to 'System.Action<object>'' An example:

                                  public class Base
                                  {
                                  public Func<object> OnComplete {get;set;}
                                  public Base(Func<object> onComplete)
                                  {
                                  OnComplete = onComplete;
                                  }
                                  }
                                  public class GenericBase<T> : Base
                                  {
                                  public GenericBase(Func<T> onComplete) : base(onComplete) //Error
                                  {
                                  OnComplete = onComplete; //Error
                                  }
                                  }

                                  ____________________________________________________________ Be brave little warrior, be VERY brave

                                  modified on Thursday, March 31, 2011 3:22 AM

                                  B Offline
                                  B Offline
                                  BobJanova
                                  wrote on last edited by
                                  #16

                                  Generic inheritance is a bit complicated. Here's the reason that you can't cast 'down' the generic type parameter inheritance tree. Imagine this test class:

                                  class BadMistake {
                                  void CompleteHandler(Dictionary<string,int> complexParameter){
                                  // some stuff
                                  }

                                  GenericBase<Dictionary<string,int>> instance;

                                  public void CauseDeath(){
                                  instance = new GenericBase<Dictionary<string,int>>(CompleteHandler);
                                  ((Base)instance).OnComplete(16);
                                  }
                                  }

                                  Now, CompleteHandler is expecting to be passed a Dictionary, and you can't compile something which would cause that not to be the case. But using the base class, you can pass an int (or anything else) to it. Method parameter compatibility for generics works backwards. This example will compile if the type parameter in the base is a subclass of T, for example try:

                                  public class Base
                                  {
                                  public Func<T> OnComplete {get;set;} where T:Panel
                                  public Base(Func<T> onComplete) where T:Panel
                                  {
                                  OnComplete = onComplete;
                                  }
                                  }
                                  public class GenericBase<T> : Base
                                  {
                                  public GenericBase(Func<T> onComplete) where T:UserControl : base(onComplete)
                                  {
                                  OnComplete = onComplete;
                                  }
                                  }

                                  (if I got the syntax on the constructor there right). Also, there isn't really a reason to make a non generic base type and inherit from it in this way. You can just use a GenericBase<object> if you want one that can deal with anything.

                                  1 Reply Last reply
                                  0
                                  • P Pete OHanlon

                                    That's exactly what I'm saying. The thing is though, generics were brought in for things like type safety and to prevent aid the developer move away from boxing/unboxing. By having object as the generic type, you've just gone back to having a boxing/unboxing issue - and you're no better off than just passing Action across rather than the generic Action.

                                    I'm not a stalker, I just know things. Oh by the way, you're out of milk.

                                    Forgive your enemies - it messes with their heads

                                    My blog | My articles | MoXAML PowerToys | Onyx

                                    A Offline
                                    A Offline
                                    Adriaan Davel
                                    wrote on last edited by
                                    #17

                                    I understand that I should avoid boxing & un-boxing (and I do want to, and I do it everywhere), in this case it's not an option. Bit of a complex scenario I'll have to explain (and the code is part of a 5 000 file solution), but I'm quite irritated that this is disallowed, I thought polymorphism / covariance / contravariance is exactly about this...

                                    ____________________________________________________________ Be brave little warrior, be VERY brave

                                    L R 2 Replies Last reply
                                    0
                                    • A Adriaan Davel

                                      I understand that I should avoid boxing & un-boxing (and I do want to, and I do it everywhere), in this case it's not an option. Bit of a complex scenario I'll have to explain (and the code is part of a 5 000 file solution), but I'm quite irritated that this is disallowed, I thought polymorphism / covariance / contravariance is exactly about this...

                                      ____________________________________________________________ Be brave little warrior, be VERY brave

                                      L Offline
                                      L Offline
                                      Lost User
                                      wrote on last edited by
                                      #18

                                      It is, for objects - aka reference-types, not for value-types. C# is really strict on the difference. The posted alternative with the interface does look like it (could) solve your problem. Alternatively, you could decide only to pass objects, and to wrap your ints in a MyInt class.

                                      I are Troll :suss:

                                      1 Reply Last reply
                                      0
                                      • A Adriaan Davel

                                        After much painfull and brain numbing reading I still don't understand why its not possible to cast between Action<T> and Action<object>, can anyone please explain this in small words (I currently have the brain of a 5 year old). There was a poem written along time ago by a person dying with lots of pain, he called it 'Brother Pain', I'm about to write a poem called 'Brother Cannot implicitly convert type 'System.Action<T>' to 'System.Action<object>'' An example:

                                        public class Base
                                        {
                                        public Func<object> OnComplete {get;set;}
                                        public Base(Func<object> onComplete)
                                        {
                                        OnComplete = onComplete;
                                        }
                                        }
                                        public class GenericBase<T> : Base
                                        {
                                        public GenericBase(Func<T> onComplete) : base(onComplete) //Error
                                        {
                                        OnComplete = onComplete; //Error
                                        }
                                        }

                                        ____________________________________________________________ Be brave little warrior, be VERY brave

                                        modified on Thursday, March 31, 2011 3:22 AM

                                        R Offline
                                        R Offline
                                        Rob Philpott
                                        wrote on last edited by
                                        #19

                                        Because it just can't. If asked questions such as this I like to mutter something about Covariance and Contravariance and wonder off. Usually works in the office environment anyway.

                                        Regards, Rob Philpott.

                                        P 1 Reply Last reply
                                        0
                                        • A Adriaan Davel

                                          I understand that I should avoid boxing & un-boxing (and I do want to, and I do it everywhere), in this case it's not an option. Bit of a complex scenario I'll have to explain (and the code is part of a 5 000 file solution), but I'm quite irritated that this is disallowed, I thought polymorphism / covariance / contravariance is exactly about this...

                                          ____________________________________________________________ Be brave little warrior, be VERY brave

                                          R Offline
                                          R Offline
                                          RobCroll
                                          wrote on last edited by
                                          #20

                                          It's a design issue and it makes sense when you think about it. If you want to use a collection of type object, then use ArrayList. The generic List is a strongly typed version of ArrayList, so if strong typing is not required, use ArrayList.

                                          "You get that on the big jobs."

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups