关于类型转换,C#与JAVA最大的不同在于C#有struct,而JAVA则没有这玩意。于是乎在C#中泛型类型转换就有一下代码(仅限struct结构)。另外一个较小的差异呢则是在C#中各struct类型都带有TryParse方法,当然,2.0以后(包括2.0)才有。
namespace DObject.DType
{
/// <summary>
/// 类型转换帮助类,静态方法实现。加入了缓存机制,减少反射次数。
/// </summary>
public static class StaticConvertor
{
private const string CONVERTMETHOD = "TryParse";
private static Dictionary<System.Type, MethodInfo> map = new Dictionary<System.Type, MethodInfo>(20);
private static MethodInfo prepareMethod(System.Type type)
{
lock (map)
{
if (!map.ContainsKey(type))
{
System.Type[] typeArray = new System.Type[2];
typeArray.SetValue(typeof(string), 0);
typeArray.SetValue(type.GetType().MakeByRefType(), 1);
MethodInfo method = type.GetType().GetMethod(CONVERTMETHOD, typeArray);
if (method != null)
{
map.Add(type, method);
}
else
return null;
}
return map[type];
}
} //end prepareMethod
/// <summary>
/// 转换方法
/// </summary>
/// <typeparam name="T">转换后类型</typeparam>
/// <param name="raw">原始对象</param>
/// <param name="defaultValue">默认值</param>
/// <param name="convertSuccessful">是否转换成功</param>
/// <returns>返回值</returns>
public static T Convert<T>(object raw, T defaultValue, out bool convertSuccessful) where T : struct
{
convertSuccessful = false;
if (raw == null) //失败
return defaultValue;
else if (raw is T) //成功
{
convertSuccessful = true;
return (T)raw;
}
else
{
try
{
object[] parms = new object[2];
parms[0] = raw.ToString();
parms[1] = 0;
bool isparser = (bool)prepareMethod(typeof(T)).Invoke(null, parms);
if (isparser) //成功
{
convertSuccessful = true;
return (T)parms[1];
}
}
catch
{
}
return defaultValue;
}
} //end Convert<T>
}
}
以上代码的写法,适合DateTime,Int32,Int64,Int16,byte,bool等。只有是struct结构,并且有TryParse方法就可以使用。而使用起来呢也很简单,如以下代码
namespace DObject.DType
{
/// <summary>
/// Int32类型保证
/// </summary>
public class DInt32 : DObject, IValuetable<Int32>, IConvertSuccess
{
private int target;
private int defaultValue = -1;
/// <summary>
/// 构造函数,对象初始化时,就执行转换
/// </summary>
/// <param name="o"></param>
public DInt32(object o)
: base(o)
{
target = StaticConvertor.Convert<int>(base.raw, defaultValue, out convertSuccessful);
}
public static implicit operator DInt32(DType type)
{
return new DInt32(type.RawObject);
}
private bool convertSuccessful;
/// <summary>
/// 返回转换值
/// </summary>
/// <returns>返回转换值,如果转换成功则返回值;转换失败返回默认值 -1</returns>
public int Value()
{
return Value(defaultValue);
}
/// <summary>
/// 返回转换值
/// </summary>
/// <param name="defaultValue">默认值</param>
/// <returns>返回转换值,如果转换成功则返回值;转换失败返回默认值</returns>
public int Value(int defaultValue)
{
if (convertSuccessful)
return target;
return defaultValue;
}
/// <summary>
/// 是否转换成功
/// </summary>
public bool ConvertSuccess
{
get { return convertSuccessful; }
}
}
}
/// <summary>
/// 构造类型,为内置类型提供构造参数。
/// <example>
/// DInt32 int32 = DType.Default("123");
/// </example>
/// </summary>
public class DType
{
private object o;
private DType(object o)
{
this.o = o;
}
/// <summary>
/// 提供对象构造参数
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public static DType Default(object o)
{
return new DType(o);
}
/// <summary>
/// 原始对象
/// </summary>
public object RawObject
{
get { return o; }
}
}
使用起来也是简单:
DInt32 int32 = DType.Default("123");
int val = int32.Value();
Java里就没这样的了,使用try捕获错误并非想要的。java里没有struct,但是有个类型Number确是可以使用。当然,这就不能像C#一样将乱七八糟的东西都整一块了,要分开来处理了。
/**
*
* @author yurow
*/
public class DNumber extends DObject {
/**
* Create new instance of DNumber
*/
protected DNumber() {
super();
}
protected DNumber(Object obj)
{
super(obj);
}
protected Boolean isconvert;
public Number Convert(Number defaultValue) {
isconvert = false;
if (obj == null) {
return defaultValue;
} else if (obj instanceof Number) {
isconvert = true;
return Number.class.cast(obj);
} else {
return defaultValue;
}
}
}
/**
*
* @author yurow
*/
public class DInt32 extends DNumber {
/**
* Create new instance of DInt32
*/
protected DInt32() {
super();
}
protected DInt32(Object obj) {
super(obj);
}
public static DInt32 newInt32(Object obj) {
return new DInt32(obj);
}
public int Convert()
{
return super.Convert(-1).intValue();
}
}
可以看出,JAVA的类型逻辑层次划分比C#要细致,处理起来当然要复杂一些。可见粒度并非越细越好。贫道看来JAVA倾向于按逻辑划分,而C#倾向于按内存布局划分。