2010-06-23 50 views
1

我有一系列的受理各种数据类型的方法C#wraper类:在运行时确定(C#)

public class MyClass 
{ 
    public void ProcessString(string Value) { // implementation } 
    public void ProcessInt(int? Value) { // implementation }\ 
    public void ProcessOther(MyClass Value) { // implementation } 
} 

我现在想添加一个通用ProcessObject()方法以避免需要调用相关的处理方法之前显式转换的对象:

public void ProcessObject(object Value) 
{ 
    if (CanCastToString(Value) 
    { 
     ProcessString((string)Value); 
    } 
    else if (CanCastToInt(Value)) 
    { 
     ProcessInt((int?)Value); 
    } 
    // etc... 
} 

麻烦的是,我不知道我的CanCastToInt方法应该是什么 - 我需要这些方法可以是稳健和处理像可为空的类型和其他用户定义的ca STS。

我该怎么做?所有我想知道的是,如果给定的对象可以转换为给定类型,即无论是否:

(SomeType)Value 

会工作。

+2

你关心*?也就是说,假设你的对象有一个盒装的短小的东西。你想能够将它转换为int吗?你不能直接将盒装短片投射到int;你必须首先将它转换为int,然后再缩写。您可能想阅读我关于这个主题的文章,以确保您了解这里发生了什么:http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx – 2010-06-23 02:03:22

+0

他们必须是盒装价值类型吗?通常情况下,执行此操作的OO方法是使用Process方法创建接口,每个类型都继承您,然后只调用对象上的方法,而不用担心它是什么类型。 – 2010-06-23 08:50:00

回答

4

主要有两种方式这通常是:

if (Value is SomeType) 
{ 
    // Do something with a cast 
} 

var v = Value as SomeType; 
if (v != null) 
{ 
    // Value was successfully cast as SomeType 
} 

当与结构或固有类型的工作,使他们可为空:

var v = Value as int?; 
if (v != null) 
{ 
    ProcessInt(v.Value); 
} 
1

您需要is运营商。 CanCastToString(x) - >x is string

+0

不起作用 - 考虑'x'为'Nullable '时的情况,然后'x是int'返回false,但是'(int)x'可以正常工作。 – Justin 2010-06-23 01:44:17

+4

@Kragen:你确定吗?假设表达式是编译时类型为空的。那么你不需要*“is”操作符,因为你已经*知道了*对象的确切类型。假设表达式不是编译时类型可空的。它可能是什么类型的? *必须装盒*。而且没有盒装可空的int这样的东西!一个可为空的int或者为null引用或者为装箱的int。 (给你一个难题:我的分析不完全正确,我错过了什么情况?) – 2010-06-23 02:00:13

-1
public void QuickTest() 
    { 
     object stringObj = "string"; 
     object nullableInt1 = (int?)null; 
     object nullableInt2 = (int?)1; 
     object decimalObj = 1.5m; 

     ProcessObject(stringObj); 
     ProcessObject(nullableInt1); 
     ProcessObject(nullableInt2); 
     ProcessObject(decimalObj); 
    } 

    public void ProcessObject(object value) 
    { 
     if (value == null) 
     { 
      Debug.WriteLine("null"); 
      return; 
     } 


     if (value is string) 
     { 
      Debug.WriteLine((string)value); 
      return; 
     } 

     string stringValue = value.ToString(); 

     int intTemp; 
     if (int.TryParse(stringValue, out intTemp)) 
     { 
      Debug.WriteLine(intTemp); 
      return; 
     } 

     decimal decimalTemp; 
     if (decimal.TryParse(stringValue, out decimalTemp)) 
     { 
      Debug.WriteLine(decimalTemp); 
      return; 
     } 
     // etc... 
    } 
1

为什么不暴露你的proc直接使用API​​,并为各种参数重载?

public class MyClass 
{ 
    public void Process(string Value) { // implementation } 
    public void Process(int Value) { // implementation }\ 
    public void Process(MyClass Value) { // implementation } 
    public void Process(object Value) { // catch all method. Handle unknown entities, e.g. call ToString() } 
} 

编辑随着一些仿制药的魔法,你可以有一个单一的接口方法,一堆的helper方法做,你处理极端情况的工作和一个包罗万象的方法。

public class MyClass 
{ 
    void DoProcess(string Value) { // implementation } 
    void DoProcess(int Value) { // implementation }\ 
    void DoProcess(MyClass Value) { // implementation } 
    void DoProcess(object Value) { 
     // catch all method. Handle unknown entities, e.g. call ToString() 
    } 
    public void Process<T>(T value) { 
     //this method will call the right overload of DoProcess depending on the compile time type of value. If there isn't a match, it goes to DoProcess(object) 
     DoProcess(value); 
    } 
} 

这样,你避免基本类型拳击,并有稍好的类型安全。

为了您的全部方法,您可以尝试使用Type.IsAssignableFrom方法。例如:

if (typeof(short).IsAssignableFrom(Value) 
    DoProcess((short)Value); 
if (typeof(byte).IsAssignableFrom(Value) 
    DoProcess((byte)Value); 

我建议您阅读Eric Lippert关于演绎演员的散文。希望在做完这些之后,你会意识到对每种支持的类型重载可能会更容易。另外,你可能会意识到,处理拆箱价值类型可能是通向地狱的道路。

+0

我已经有了,但是我也希望公开一个使用对象的泛型方法,因为它使得其他地方更容易。 – Justin 2010-06-23 06:33:53