c# 4.0引入了一种叫做“动态”的新类型。这听起来不错,但是程序员要用它来做什么呢?
在某种情况下,它是否可以挽救局面?
c# 4.0引入了一种叫做“动态”的新类型。这听起来不错,但是程序员要用它来做什么呢?
在某种情况下,它是否可以挽救局面?
当前回答
动态类型的另一个用例是遇到协方差或逆变问题的虚拟方法。一个这样的例子是臭名昭著的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
}
}
其他回答
你可以使用pythonnet调用动态语言,比如CPython:
充满活力。
在对泛型应用数值运算符时,可以将泛型强制转换为动态泛型。这提供了类型安全性并避免了泛型的限制。这本质上是*鸭子打字:
T y = x *(动态)x,其中typeof(x)为T
动态类型的另一个用例是遇到协方差或逆变问题的虚拟方法。一个这样的例子是臭名昭著的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
}
}
它使静态类型语言(CLR)更容易与运行在DLR(动态语言运行库)上的动态语言(python, ruby…)互操作,参见MSDN:
例如,您可以使用下面的代码来增加一个计数器 在XML和c#中。 Scriptobj。SetProperty("Count", ((int)GetProperty("Count")) + 1); 通过使用DLR,可以使用下面的代码来代替 同样的操作。 scriptobj。计数+= 1;
MSDN列出了以下优点:
简化将动态语言移植到。net框架 在静态类型语言中启用动态特性 提供DLR和.NET框架的未来好处 启用库和对象的共享 提供快速动态分派和调用
详情请参阅MSDN。
用法示例:
你使用了许多具有共同属性'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;
}
The best use case of dynamic type variables for me was when, recently, I was writing a data access layer in ADO.NET (using SQLDataReader) and the code was invoking the already written legacy stored procedures. There are hundreds of those legacy stored procedures containing bulk of the business logic. My data access layer needed to return some sort of structured data to the business logic layer, C# based, to do some manipulations (although there are almost none). Every stored procedure returns different set of data (table columns). So instead of creating dozens of classes or structs to hold the returned data and pass it to the BLL, I wrote the below code which looks quite elegant and neat.
public static dynamic GetSomeData(ParameterDTO dto)
{
dynamic result = null;
string SPName = "a_legacy_stored_procedure";
using (SqlConnection connection = new SqlConnection("my connection string"))
{
SqlCommand command = new SqlCommand(SPName, connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@empid", dto.EmpID));
command.Parameters.Add(new SqlParameter("@deptid", dto.DeptID));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
dynamic row = new ExpandoObject();
row.EmpName = reader["EmpFullName"].ToString();
row.DeptName = reader["DeptName"].ToString();
row.AnotherColumn = reader["AnotherColumn"].ToString();
result = row;
}
}
}
return result;
}