public static Ret?To <Ret>(this object?obj, bool @throw = true, LazyPro <Ret>?notConvert = default) { var type = typeof(Ret); try { switch (obj) { case Ret a: return(a); case { } a when Tool.SpecialConversion.TryGetValue((a.GetType(), type), out var convert): //如果不能直接转换,则尝试调用已注册的特殊转换 return((Ret)convert(obj)); case IConvertible a: return((Ret)Convert.ChangeType(a, type.IsGenericRealize(typeof(Nullable <>)) ? type.GenericTypeArguments[0] : type)); //如果目标类型是可空值类型,则将其转换为它的泛型类型 default: dynamic?dy = obj; //如果上述转换全部失败,则尝试调用该类型自定义的转换 return((Ret?)dy); } #region 说明文档 /*说明: * 上面那个switch看上去可以简化为这种形式: * * if(Obj is IConvertible a) * { * var toType = type.FullName.StartsWith("System.Nullable") ? * type.GenericTypeArguments[0] : type; * return (Ret)Convert.ChangeType(a, toType); * } * dynamic dy = Obj; * return (Ret)dy; * * 但实际上不可以,这是因为: * 假如Obj实现了IConvertible,但是要转换的目标类型是Obj的子类 * 那么程序会错误的调用ChangeType,导致转换失败 * 这种情况虽然非常少见,但如果置之不理,会埋下一个隐患*/ #endregion } catch (Exception) { return(@throw ? throw new ExceptionTypeUnlawful(obj, type) : notConvert !); } }
public (bool Exist, A?Value) TryGetValue(B Key, LazyPro <A>?NoFound = null) => BToA.TryGetValue(Key, NoFound);
public (bool Exist, B?Value) TryGetValue(A Key, LazyPro <B>?NoFound = null) => AToB.TryGetValue(Key, NoFound);