[英]Generic interface property is virtual in implementation
我有一個名為“ Entity”的模型,該模型實現了“ IEntity”接口,如下所示(簡化):
public interface IEntity<T> where T : IComparable
{
T Id { get; set; }
}
public class Entity: IEntity<Guid>
{
public Guid Id { get; set; }
public Guid LayoutId { get; set; }
public virtual Layout Layout {get; set;}
}
我想克隆此“實體”模型的對象,同時忽略以下虛擬屬性:
public static class CloneHelper
{
public static T CloneNonVirtual<T>(this T source) where T : class
{
var cloneObj = Activator.CreateInstance<T>();
foreach (var prop in source.GetType().GetProperties().Where(w => w.CanWrite && !w.GetAccessors().Any(x => x.IsVirtual)))
{
var cloneObjProp = cloneObj.GetType().GetProperty(prop.Name);
cloneObjProp.SetValue(cloneObj, prop.GetValue(source));
}
return cloneObj;
}
}
在這里,問題在於LayoutId的訪問器不是虛擬的,而Id的訪問器是虛擬的! 請同時查看兩個QuickWatch窗口:
為什么會發生這種情況? 這是因為Id是通用接口“ IEntity”的實現屬性嗎? 如果是這樣,並且這是預期的行為,為什么?
謝謝,
功力
簡短的版本是這就是CLR的工作方式。 請注意MethodBase
文檔中的這段文字:
公共語言運行時要求所有實現接口成員的方法都必須標記為虛擬
換句話說:之所以這樣,是因為CLR表示必須采用這種方式。
更一般而言,當在編譯時不知道要分派的方法時,將使用虛擬方法。 對於未聲明為virtual
方法且未實現某些接口成員的方法,C#編譯器可以在編譯時確定要調用的方法,並可以在IL中生成特定的,效率更高的方法調用類型,以用於這個目的。
對於其他方法,可能需要從實際實現類型未知的上下文中調用它們,因此必須通過方法表( “ vtable” )路由對此類方法的調用。 這既適用於實際的virtual
方法(即,這樣聲明的方法),也適用於實現接口成員的方法,因為可以從(通常是)從上下文中調用后一種方法,在該上下文中,所有已知的只是接口類型,而不是實際的實現類型。 通過使用vtable,調用者只需知道vtable的位置和格式,而不是實現類型即可。
因為真正的virtual
方法和接口成員的功能基本相同,所以在底層CLR實現級別上,它們都被視為相同。 (通常…在文檔中也要注意,接口實現成員也被標記為final
,指示它們不能被覆蓋)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.