2009-01-21 13 views
17

Yapmam gereken şey şu:Bir değişkeni başka bir değişkende depolanmış bir türe dökmek mümkün mü?

object foo = GetFoo(); 
Type t = typeof(BarType); 
(foo as t).FunctionThatExistsInBarType(); 

Böyle bir şey yapılabilir mi?

+0

bunu size son satırında eşitleri sol tarafında istediğiniz bir dizesi olduğunu nasıl anlarsınız örneğiniz Başka bir deyişle, "object bar = (object) foo" yu kullanamayacağınız anlamına gelen çubukla ne yapacaksınız? ? –

+0

Yapamam, string sadece bir örnekti. Snippet'i düzenledim. –

cevap

13

Hayır, yapamazsınız. C#, duck typing'u uygulamıyor.

Bir arabirim uygulayıp ona yayın yapmalısınız.

(Ancak bunu yapmak için girişimleri vardır. Örnek için Duck Typing Project bakın.)

+0

Evet yapabilirsin. GvS'nin cevabına bakın :-) –

+1

Hala arayüzü (bu durumda IConvertible) uygulamanız ve önceden türetilmekte olan türü bilmeniz gerekiyor. – Quassnoi

+0

Bu cevabı kabul edildi olarak işaretledim, çünkü Quassnoi'nin tavsiyesini kullandım ve ona bir arayüz hazırladım, ama GvS'nin ve shuggycouk'un cevapları da harika. –

20

Sen Convert.ChangeType yöntemi kullanabilirsiniz.

object foo = GetFoo(); 
Type t = typeof(string); 
string bar = (string)Convert.ChangeType(foo, t); 
+6

Bu, yalnızca nesne IConvertible – Quassnoi

+4

uygularsa kullanışlıdır, yalnızca bir örnek olarak dizeyi kullandım. Sorun hedef türünü bilmiyorum, bu yüzden xyz bar = (xyz) Convert.Change ... cast yapamıyorum. –

+0

Convert.ChangeType, dönüştürme değil. yani belirtilen tipte yeni bir nesne yaratmak. ICollection söylemek için dökmek istiyorsanız bu işe yaramaz. – Hoots

4

Orijinal soru derleme zamanında bilinen ancak değişken bildirmek zaman sol tarafta tanımlanmış bir dize sahip olduğuna dikkat edilmeyen bir türü olarak bir değişken tedavi etmek sormak içinde hatalıydı. C# 3,5'den itibaren statik olarak yazılmıştır.

kez dinamik Böyle bir şey yapabileceğini daha mevcuttur: tip ne olduğunu bilmiyorum için

dynamic foo = GetFoo(); 
foo.FunctionThatExistsInBarType(); 

ama bunu her zaman) (Örnek yöntemi FunctionThatExistsInBarType destekleyeceğini biliyorum; Şimdilik yansıma (veya aynı şeyden çok ama aynı zamanda daha pahalı ve daha pahalı olan kod genini) kullanmak zorundasınız.

// any of these can be determined at runtime 
Type t = typeof(Bar); 
string methodToCall = "FunctionThatExistsInBarType"; 
Type[] argumentTypes = new Type[0]; 
object[] arguments = new object[0]; 
object foo; 
// invoke the method - 
// example ignores overloading and exception handling for brevity 
// assumption: return type is void or you don't care about it 
t.GetMethod(methodToCall, BindingFalgs.Public | BindingFlags.Instance) 
    .Invoke(foo, arguments); 
+1

Dize türü sadece bir örnekti (iyi değil); Kod snippet'ini düzenledim, şimdi umuyoruz. –

+0

Doğru - bunun için (ön dinamik) yansımayı kullanmalısınız. Bunu – ShuggyCoUk

0

Eğer derleme sırasında gerekli tüm türlerini biliyor koşuluyla, duck typing (çeşit) mümkündür:

class BarFoo {} 
class Foo {} 
class Bar {} 

class Program 
{ 
    static void Main() 
    { 
     var foo = new Foo(); 
     var bar = new Bar(); 
     var barfoo = new BarFoo(); 

     Console.WriteLine(DoStuff(foo)); 
     Console.WriteLine(DoStuff(bar)); 
     Console.WriteLine(DoStuff(barfoo)); 

    } 

    static string DoStuff(Foo foo) { return "DoStuff(Foo foo)"; } 
    static string DoStuff(Bar bar) { return "DoStuff(Bar bar)"; } 
    static string DoStuff(Base fb) { return "DoStuff(object fb)"; } 
} 

Çıktı: Eğer bir sürü uygulayan sonunda ise

Dostuff(Foo foo) 
Dostuff(Bar bar); 
DoStuff(object fb); 

Temelde aynı şeyi yapan yöntemler, bir arayüzün uygulanmasını düşünün. dinamikleri C# eklendi yana

+0

Uh hesaba katmak için düzenleyeceğim .. Dört yıl sonra .. Oh iyi. –

+2

Bu, ördek yazmıyor. Bu polimorfizmdir ('DoStuff' işlevine uygulanır). –

2

, biz bu şekilde yapabiliriz düşünüyorum:

class Program { 
    static void Main(string[] args) { 
     List<int> c = new List<int>(); 
     double i = 10.0; 
     Type intType = typeof(int); 
     c.Add(CastHelper.Cast(i, intType)); // works, no exception! 
    } 
} 

class CastHelper { 
    public static dynamic Cast(object src, Type t) { 
     var castMethod = typeof(CastHelper).GetMethod("CastGeneric").MakeGenericMethod(t); 
     return castMethod.Invoke(null, new[] { src }); 
    } 
    public static T CastGeneric<T>(object src) { 
     return (T)Convert.ChangeType(src, typeof(T)); 
    } 
} 
+1

Bu, diğer çözümlerin olmadığı bir çekicilik gibi çalıştı. – BrotherOdin

+0

Mükemmel, teşekkürler! – Stark

İlgili konular