2

Following this question, I see it's possible to pass a type to a method. Inside the method to which the type has been passed, how would an object be cast to that passed type? As a complication, class Foo inherits from a class which I cannot change.

 var x = FetchData();
 Foo foo = new Foo(2, typeof(Gizmo));   // pass the Gizmo type
 foo.Execute(x);


public class Foo :  ThirdPartyLibrary.Operation
{
    Type customtype;


     public Foo(int i, Type passedtype)  : base()
     {
          this.customtype=passedtype;
     }

     public override void Execute(ThirdPartyLibrary.Node node)
     {
         var record = ( ??? ) node.GetData();     // cast node to the type of customtype
     }
}
Tim
  • 8,669
  • 31
  • 105
  • 183
  • You can´t, as casting is a compile-time-operation whereby you provide the actual type at runtime. What do you want to do with `record` afterwards? Maybe you can use an interface to cast to? – MakePeaceGreatAgain Nov 09 '17 at 15:51
  • Can it be done with generics? node is being cast to a custom datatype. – Tim Nov 09 '17 at 15:51
  • You cannot. You can however, do other things that might come in handy, for different requirements. Can you explain what you want to do with it? What do you need that typed variable for? – nvoigt Nov 09 '17 at 15:52
  • Maybe, but that depends on what you actually want to do. Basically yopu can´t expect the *compiler* to infer a type you provide at *runtime*. – MakePeaceGreatAgain Nov 09 '17 at 15:52
  • 2
    Such a cast would be completely meaningless, since you wouldn't be able to do anything with the result. What are you trying to accomplish? You probably want generics. – SLaks Nov 09 '17 at 15:54
  • Maybe you want [`Convert.ChangeType`](https://msdn.microsoft.com/library/dtb69x08(v=vs.110).aspx)? – MakePeaceGreatAgain Nov 09 '17 at 15:57
  • `node.GetData()` returns object. I would like to work with object's properties. – Tim Nov 09 '17 at 15:59
  • Since the type could be anything, you'd need to use reflection, in order to access the properties of your object. – Emerson Cardoso Nov 09 '17 at 16:00
  • How does that object look like? Does it implement an interface to which you can cast? Some common base-class that contains the members you want to call on te result? Without providing what `GetData` is, it´s impossible to give you any answer. – MakePeaceGreatAgain Nov 09 '17 at 16:01
  • 1
    Create an interface called `IHasData` that has a `GetData()` method and have your custom datatypes implement it. Then change the `node` parameter's type to `IHasData`. Voila. – itsme86 Nov 09 '17 at 16:01
  • `new Foo(2, node => { Gizmo data = (Gizmo) node.GetData() })`. `Foo(int i, Action execute)`. In essence, make `Foo` an adaptor with a pluggable implementation. You can actually doll this up with a generic method that spits out `Foo` on the fly. – Jeroen Mostert Nov 09 '17 at 16:03
  • 1
    Give me a little time to digest these suggestions, as this is new to me. Thanks for them. – Tim Nov 09 '17 at 16:06

1 Answers1

2

If I'm understanding your question correctly, you can do this with generics. It would look something like this (based off your example code):

public class Foo<T> : ThirdPartyLibrary.Operation
{
    public Foo(int i) : base()
    {
         //hopefully you actually do something useful with "i" here.
    }

    public override void Execute(ThirdPartyLibrary.Node node)
    {
        //I'm not 100% sure which object you are trying to cast, so I'm showing both forms below.  You obviously won't be able to do both without changing the variable name.

        //If you want to cast the "Data", use this.
        var record = (T) node.GetData();

        //If you want to cast "node", use this.
        var record = ((T) node).GetData();
    }
}

You use it this way:

var x = FetchData();
Foo foo = new Foo<Gizmo>(2); 
foo.Execute(x);

customtype is no longer required, as you can access to the Type of T with typeof(T) from anywhere within the class.

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
  • 1
    My understanding is that OP is trying to cast `node` to a different type, so it would be `((T)node).GetData()`. – itsme86 Nov 09 '17 at 16:05
  • I believe you may be correct. Answer updated to show both forms, just in case. – Bradley Uffner Nov 09 '17 at 16:06
  • Just as an asside: this works only if you know the type `Gizmo` at compile-time. Otherwise generics don´t help at all. – MakePeaceGreatAgain Nov 09 '17 at 16:35
  • @HimBromBeere That's true. This method also won't really give you access to properties and methods of `record` unless you add a generic constraint, or use this as an abstract base class for a closed-generic sub-class. Another option would be to simply use `dynamic`, but that opens a whole other can of worms. – Bradley Uffner Nov 09 '17 at 16:42