Cri*_*scu 15 .net java generics casting
我是一个.NET人,所以让我首先断言我对一些Java概念的理解 - 如果我错了,请纠正我.
Java Generics支持有界通配符的概念:
class GenericClass< ? extends IInterface> { ... }
Run Code Online (Sandbox Code Playgroud)
...类似于.NET where限制:
class GenericClass<T> where T: IInterface { ... }
Run Code Online (Sandbox Code Playgroud)
Java的Class类描述了一个类型,并且大致相当于.NET Type类
到现在为止还挺好.但是我找不到足够接近Java的通用类型Class<T>,其中T是有界通配符.这基本上对所Class代表的类型施加了限制.
让我举一个Java的例子.
String custSortclassName = GetClassName(); //only known at runtime,
// e.g. it can come from a config file
Class<? extends IExternalSort> customClass
= Class.forName("MyExternalSort")
.asSubclass(IExternalSort.class); //this checks for correctness
IExternalSort impl = customClass.newInstance(); //look ma', no casting!
Run Code Online (Sandbox Code Playgroud)
我在.NET中最接近的是这样的:
String custSortclassName = GetClassName(); //only known at runtime,
// e.g. it can come from a config file
Assembly assy = GetAssembly(); //unimportant
Type customClass = assy.GetType(custSortclassName);
if(!customClass.IsSubclassOf(typeof(IExternalSort))){
throw new InvalidOperationException(...);
}
IExternalSort impl = (IExternalSort)Activator.CreateInstance(customClass);
Run Code Online (Sandbox Code Playgroud)
Java版本看起来更干净.有没有办法改进.NET版本?
使用扩展方法和自定义包装类System.Type,您可以非常接近 Java 语法。
注意: Type.IsSubclassOf不能用于测试类型是否实现接口 - 请参阅 MSDN 上的链接文档。人们可以使用它Type.IsAssignableFrom来代替 - 请参阅下面的代码。
using System;
class Type<T>
{
readonly Type type;
public Type(Type type)
{
// Check for the subtyping relation
if (!typeof(T).IsAssignableFrom(type))
throw new ArgumentException("The passed type must be a subtype of " + typeof(T).Name, "type");
this.type = type;
}
public Type UnderlyingType
{
get { return this.type; }
}
}
static class TypeExtensions
{
public static Type<T> AsSubclass<T>(this System.Type type)
{
return new Type<T>(type);
}
}
// This class can be expanded if needed
static class TypeWrapperExtensions
{
public static T CreateInstance<T>(this Type<T> type)
{
return (T)Activator.CreateInstance(type.UnderlyingType);
}
}
Run Code Online (Sandbox Code Playgroud)
(仅应在评估性能后在生产代码中使用。可以通过使用(并发!)缓存字典来改进ConcurrentDictionary<System.Type, IType<object>)
使用C# 4.0 中引入的一项功能 和实现的Covariant type parameters附加类型,可以使类似以下的事情成为可能:interface IType<out T>Type<T>
// IExternalSortExtended is a fictional interface derived from IExternalSort
IType<IExternalSortExtended> extendedSort = ...
IType<IExternalSort> externalSort = extendedSort; // No casting here, too.
Run Code Online (Sandbox Code Playgroud)
人们甚至可以这样做:
using System;
interface IType<out T>
{
Type UnderlyingType { get; }
}
static class TypeExtensions
{
private class Type<T> : IType<T>
{
public Type UnderlyingType
{
get { return typeof(T); }
}
}
public static IType<T> AsSubclass<T>(this System.Type type)
{
return (IType<T>)Activator.CreateInstance(
typeof(Type<>).MakeGenericType(type)
);
}
}
static class TypeWrapperExtensions
{
public static T CreateInstance<T>(this IType<T> type)
{
return (T)Activator.CreateInstance(type.UnderlyingType);
}
}
Run Code Online (Sandbox Code Playgroud)
这样就可以(明确地)在不相关的接口之间进行转换,InterfaceA例如InterfaceB:
var x = typeof(ConcreteAB).AsSubclass<InterfaceA>();
var y = (IType<InterfaceB>)x;
Run Code Online (Sandbox Code Playgroud)
但这有点违背了练习的目的。
| 归档时间: |
|
| 查看次数: |
726 次 |
| 最近记录: |