Objectを実際の型にキャストする方法は?


120

私が持っている場合:

void MyMethod(Object obj) {   ...   }

obj実際のタイプにキャストするにはどうすればよいですか?


2
型はコンパイル時にわかりますか?
psubsee2003

1
そして、あなたはこれから何を成し遂げると思いますか?達成を期待する方法ではなく、達成しようとしていることを教えてください。
Jon Skeet、2012

@JonSkeet:オブジェクトから関数を呼び出せるようにしたい。obj.MyFunction();実際のオブジェクトにその機能があることはわかっていますが、現在はコンパイルされません。
Paul Lassiter

@ psubsee2003:いいえ、それは相互運用機能を介して渡されるオブジェクト参照であるため、ありません。
Paul Lassiter

3
@PaulLassiter:タイプがわからない場合、MyFunctionメソッドは何を宣言していますか?
Jon Skeet、2012

回答:


194

実際のタイプがわかっている場合は、次のようにします。

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

実際のタイプがわからない場合は、そうではありません。代わりに次のいずれかを使用する必要があります。

  • 反射
  • よく知られたインターフェースの実装
  • 動的

例えば:

// 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
Swiftの同等の構文は何ですか?
Nagendra Rao

1
ネバーマインド、as型キャストとtype(of: ClassName)インスタンスタイプをチェックする機能が見つかりました。
Nagendra Rao

42

(リフレクションなしではありませんが)できるとは思わないので、関数にも型を指定する必要があります。

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

UPD

これはあなたのために働くかもしれません:

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

4
これは実際には役に立たない答えであり、賛成投票に値しないものです。オブジェクトタイプのオブジェクトをリフレクションしても、OPからの質問どおり、オブジェクトの「実際のタイプ」は得られません。また、objはタイプAであり、タイプBである可能性があるため、MyMethodロジックに欠陥があります。ロジックは「OPの要求どおりに」「実際のタイプ」を提供しません。互換性のあるタイプを提供し、必ずしもそうではありませんその時に希望のタイプ。
Jazimov 2018

obj.GetType()を使用してください。これは間違いなく実際のタイプを返します。
JSON

3

JsonConvert.DeserializeObject(object.ToString());はどうでしょうか。


これは満足のいく答えではありません。OPの質問は、Jsonまたはシリアル化とは関係ありません。

@ user12637955これは実際には有効な答えですが、ボックス化とボックス化解除、つまりオブジェクト-> ToString()->具象型への変換が原因で、より複雑になります。:より正確には、それは次のようになりますvar myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
コーラ

1

私の場合、AutoMapperはうまく機能します。

AutoMapperは、明示的な構成なしで動的オブジェクトとの間でマップできます。

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);

同様に、ディクショナリからオブジェクトに直接マップできます。AutoMapperは、キーとプロパティ名を並べます。

詳細情報https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping


1

この方法は最も効率的ではないかもしれませんが、単純であり、仕事をします。

これは2つの操作を実行します。最初に基本的にシリアル化である.ToString()を呼び出し、次にNewtonsoft nuget(インストールする必要があります)を使用して逆シリアル化します。

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

将来の読者のために、答えを簡単に説明してください。
Suraj Kumar

0

MyFunction()メソッドが1つのクラス(およびその子孫)でのみ定義されている場合は、

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

呼び出す関数を定義する無関係なクラスが多数ある場合は、インターフェースを定義し、クラスにそのインターフェースを定義させる必要があります。

interface IMyInterface
{
    void MyFunction();
}

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

0

たとえば、型がabcという名前のクラスから指向されている場合は、実際の型にキャストします。この方法で関数を呼び出すことができます:

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

関数がわからない場合は、別の方法で実行できます。いつも簡単ではありません。しかし、あなたはそれをシグネチャで見つけることができます。これがあなたのケースであるならば、あなたは私たちに知らせるべきです。


-1

実際の型へのキャストは簡単です:

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

8
これは非論理的です。実際のタイプは実際にはわかりません。どうやってそうするの?
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 );
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.