c# 4.0引入了一种叫做“动态”的新类型。这听起来不错,但是程序员要用它来做什么呢?
在某种情况下,它是否可以挽救局面?
c# 4.0引入了一种叫做“动态”的新类型。这听起来不错,但是程序员要用它来做什么呢?
在某种情况下,它是否可以挽救局面?
当前回答
用法示例:
你使用了许多具有共同属性'CreationDate'的类:
public class Contact
{
// some properties
public DateTime CreationDate { get; set; }
}
public class Company
{
// some properties
public DateTime CreationDate { get; set; }
}
public class Opportunity
{
// some properties
public DateTime CreationDate { get; set; }
}
如果你写一个通用的方法来检索'CreationDate'属性的值,你必须使用反射:
static DateTime RetrieveValueOfCreationDate(Object item)
{
return (DateTime)item.GetType().GetProperty("CreationDate").GetValue(item);
}
使用“动态”概念,你的代码会更加优雅:
static DateTime RetrieveValueOfCreationDate(dynamic item)
{
return item.CreationDate;
}
其他回答
COM互操作。尤其是IUnknown。这是专门为它设计的。
动态类型的另一个用例是遇到协方差或逆变问题的虚拟方法。一个这样的例子是臭名昭著的Clone方法,该方法返回与调用它的对象类型相同的对象。动态返回并不能完全解决这个问题,因为它绕过了静态类型检查,但至少你不需要像使用普通对象一样一直使用丑陋的类型转换。换句话说,类型转换是隐式的。
public class A
{
// attributes and constructor here
public virtual dynamic Clone()
{
var clone = new A();
// Do more cloning stuff here
return clone;
}
}
public class B : A
{
// more attributes and constructor here
public override dynamic Clone()
{
var clone = new B();
// Do more cloning stuff here
return clone;
}
}
public class Program
{
public static void Main()
{
A a = new A().Clone(); // No cast needed here
B b = new B().Clone(); // and here
// do more stuff with a and b
}
}
我很惊讶没有人提到多重调度。解决这个问题的通常方法是通过访问者模式,这并不总是可能的,所以你最终会得到堆叠的支票。
这是我自己的一个应用实例。而不是做:
public static MapDtoBase CreateDto(ChartItem item)
{
if (item is ElevationPoint) return CreateDtoImpl((ElevationPoint)item);
if (item is MapPoint) return CreateDtoImpl((MapPoint)item);
if (item is MapPolyline) return CreateDtoImpl((MapPolyline)item);
//other subtypes follow
throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}
你该怎么做:
public static MapDtoBase CreateDto(ChartItem item)
{
return CreateDtoImpl(item as dynamic);
}
private static MapDtoBase CreateDtoImpl(ChartItem item)
{
throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}
private static MapDtoBase CreateDtoImpl(MapPoint item)
{
return new MapPointDto(item);
}
private static MapDtoBase CreateDtoImpl(ElevationPoint item)
{
return new ElevationDto(item);
}
注意,在第一种情况下,ElevationPoint是mappointment的子类,如果它没有放在mappointment之前,它将永远不会被到达。dynamic则不是这样,因为最接近的匹配方法将被调用。
正如您可能从代码中猜到的那样,当我执行从ChartItem对象到其可序列化版本的转换时,该特性非常方便。我不想用访问者污染我的代码,我也不想用无用的序列化特定属性污染我的ChartItem对象。
你可以使用pythonnet调用动态语言,比如CPython:
充满活力。
在对泛型应用数值运算符时,可以将泛型强制转换为动态泛型。这提供了类型安全性并避免了泛型的限制。这本质上是*鸭子打字:
T y = x *(动态)x,其中typeof(x)为T
它在运行时求值,所以你可以像在JavaScript中那样切换类型到你想要的任何类型。这是正确的:
dynamic i = 12;
i = "text";
所以你可以根据需要改变类型。把它作为最后的手段;这是有益的,但我听说在生成IL的场景下发生了很多事情,这可能以性能代价为代价。