Come lanciare Object nel suo tipo attuale?


121

Se ho:

void MyMethod(Object obj) {   ...   }

Come posso eseguire il cast objsu qual è il suo tipo effettivo?


2
Il tipo è noto in fase di compilazione?
psubsee2003

1
E cosa ti aspetti di ottenere da questo? Per favore dicci cosa stai cercando di ottenere, piuttosto che come ti aspetti di ottenerlo.
Jon Skeet

@ JonSkeet: voglio essere in grado di chiamare una funzione dall'oggetto. Attualmente obj.MyFunction();non si compila, anche se so che l'oggetto reale ha quella funzione.
Paul Lassiter

@ psubsee2003: no, perché è un riferimento a un oggetto passato tramite interop.
Paul Lassiter

3
@PaulLassiter: Se non conosci il tipo, cosa dichiara il MyFunctionmetodo?
Jon Skeet

Risposte:


194

Se conosci il tipo effettivo, allora semplicemente:

SomeType typed = (SomeType)obj;
typed.MyFunction();

Se non conosci il tipo effettivo, allora: non proprio, no. Dovresti invece usare uno di:

  • riflessione
  • implementando un'interfaccia ben nota
  • dinamico

Per esempio:

// reflection
obj.GetType().GetMethod("MyFunction").Invoke(obj, null);

// interface
IFoo foo = (IFoo)obj; // where SomeType : IFoo and IFoo declares MyFunction
foo.MyFunction();

// dynamic
dynamic d = obj;
d.MyFunction();

1
Qual è la sintassi equivalente in Swift?
Nagendra Rao

1
Non importa, trovato asper typecasting e type(of: ClassName)funzione per controllare il tipo di istanza.
Nagendra Rao

43

Non penso che tu possa (non senza riflessione), dovresti fornire anche un tipo alla tua funzione:

void MyMethod(Object obj, Type t)
{
    var convertedObject = Convert.ChangeType(obj, t);
    ...
}

UPD :

Questo potrebbe funzionare per te:

void MyMethod(Object obj)
{
    if (obj is A)
    {
        A a = obj as A;
        ...
    } 
    else if (obj is B)
    {
        B b = obj as B;
        ...
    }
}

4
Questa è davvero una risposta inutile, immeritevole di voti positivi. La riflessione di un oggetto di tipo oggetto non produrrà il "tipo effettivo" dell'oggetto, come richiesto da OP. Inoltre, la tua logica MyMethod è difettosa perché obj può essere di tipo A e può anche essere di tipo B. La tua logica non fornisce il "tipo effettivo" (come richiesto dall'OP) - fornisce un tipo compatibile, e non necessariamente il tipo desiderato a quello.
Jazimov

usa obj.GetType (). Ciò restituirà sicuramente il suo tipo reale.
JSON

3

Che ne dici di JsonConvert.DeserializeObject (object.ToString ());


Questa non è una risposta soddisfacente. La domanda di OP non ha nulla a che fare con Json o serializzazione.

@ user12637955 questa è in realtà una risposta funzionante, ma ha una complessità maggiore, a causa del boxing e unboxing, cioè object -> ToString () -> al tipo concreto. Per essere più precisi dovrebbe assomigliare a questo:var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
Coca Cola il

1

Nel mio caso AutoMapper funziona bene.

AutoMapper può eseguire il mapping a / da oggetti dinamici senza alcuna configurazione esplicita:

public class Foo {
    public int Bar { get; set; }
    public int Baz { get; set; }
}
dynamic foo = new MyDynamicObject();
foo.Bar = 5;
foo.Baz = 6;

Mapper.Initialize(cfg => {});

var result = Mapper.Map<Foo>(foo);
result.Bar.ShouldEqual(5);
result.Baz.ShouldEqual(6);

dynamic foo2 = Mapper.Map<MyDynamicObject>(result);
foo2.Bar.ShouldEqual(5);
foo2.Baz.ShouldEqual(6);

Allo stesso modo puoi mappare direttamente dai dizionari agli oggetti, AutoMapper allineerà le chiavi con i nomi delle proprietà.

maggiori informazioni https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping


1

Questo metodo potrebbe non essere il più efficiente ma è semplice e fa il lavoro.

Esegue due operazioni: in primo luogo chiama .ToString () che è fondamentalmente una serializzazione, e poi la deserializzazione utilizzando Newtonsoft nuget (che devi installare).

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());

Dovresti descrivere brevemente la tua risposta per i futuri lettori.
Suraj Kumar,

0

Se il tuo MyFunction()metodo è definito solo in una classe (e nei suoi discendenti), prova

void MyMethod(Object obj) 
{
    var o = obj as MyClass;
    if (o != null)
        o.MyFunction();
}

Se hai un numero elevato di classi non correlate che definiscono la funzione che desideri chiamare, dovresti definire un'interfaccia e fare in modo che le tue classi definiscano quell'interfaccia:

interface IMyInterface
{
    void MyFunction();
}

void MyMethod(Object obj) 
{
    var o = obj as IMyInterface;
    if (o != null)
        o.MyFunction();
}

0

Trasmettilo al suo tipo reale se ora il tipo ad esempio è orientato dalla classe chiamata abc. Puoi chiamare la tua funzione in questo modo:

(abc)(obj)).MyFunction();

se non conosci la funzione puoi farlo in modo diverso. Non sempre facile. Ma puoi trovarlo in qualche modo dalla sua firma. Se questo è il tuo caso, dovresti farcelo sapere.


-1

Trasmettere al tipo reale è facile:

void MyMethod(Object obj) {
    ActualType actualyType = (ActualType)obj;
}

8
Questo è illogico. In realtà non conosci il tipo reale. Come dovresti farlo?
Allen Linatoc

-2
Implement an interface to call your function in your method
interface IMyInterface
{
 void MyinterfaceMethod();
}

IMyInterface MyObj = obj as IMyInterface;
if ( MyObj != null)
{
MyMethod(IMyInterface MyObj );
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.