Define class with itself as generic implementation. Why/how does this work?
Define class with itself as generic implementation. Why/how does this work?
问题:
I've normally been creating Prism Events used by the EventAggregator like:
public class SomeEvent : CompositePresentationEvent<SomeEventArgs> { }
public class SomeEventArgs
{
public string Name { get; set; }
}
But while looking at a co-workers code I noticed they did:
public class SomeEvent : CompositePresentationEvent<SomeEvent>
{
public string Name { get; set; }
}
I guess my first question is why does this even compile? It seems to me that it's implementing a class that isn't defined yet. And second, does it negatively affect the application at all, is it negligible, or better?
解答:
I guess my first question is why does this even compile?
Which rule in the spec do you believe it's violating? 没有违反编译的规则
It seems to me that it's implementing a class that isn't defined yet.
I think you'd have to specify the exact meaning of each of those terms for the statement to be judged as accurate or not. The compiler knows about CompositePresentationEvent
as it's declared elsewhere (presumably) and it knows about SomeEvent
because that's the class being declared. It's like having a field of type Foo
within a class Foo
- entirely valid.
It's also very useful to be able to do this - particularly for comparisons. For example:
public sealed class Foo : IComparable<Foo>
says that any instance of class Foo
knows how to compare itself with another instance, so it can be used for sorting in a type-safe way. In the case of structs, this also allows you to reduce boxing, as calling x.CompareTo(y)
won't need any boxing when x
is known to be of a type which implements IComparable<>
appropriately.
Note that types can get far more interestingly and confusingly recursive. Take this (slightly modified) example from my port of Protocol Buffers:
public interface IMessage<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder>
public interface IBuilder<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder>
Here, the aim is to basically end up with two types - a "message" and a "builder" so that you can always construct each from the other. For example:
public class Foo : IMessage<Foo, FooBuilder>
{
...
}
public class FooBuilder : IBuilder<Foo, FooBuilder>
{
...
}
Curiously recurring template pattern
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Declaring a Class as a Member of itself
回答1
Because it's static and therefore there is only one copy of the variable instance
within the AppDomain.
What you're thinking of is this:
public class Foo
{
private Foo lol = new Foo();
}
Notice, everything here is instance, not static.
As the commenters noted (long ago), this is valid syntactically, but would result in a StackOverflowException being thrown, as the assignment requires construction, and construction creates a new assignment. One triggers the other in a cycle that ends when the call stack reaches its maximum length.
In OP's example, assignment requires construction, but the assignment is triggered by the static constructor, not the instance constructor. The static constructor only executes once within an AppDomain, in order to initialize the class' Type. It isn't triggered by instance construction, and so (in OP's example) won't result in a stack overflow.
回答2
This is a software pattern known as "Singleton". 单例就是持有了自己类型的一个静态属性
Some people frown upon the use of the pattern for more reasons than just stated in the question but for better or for worse it is a common pattern in the .NET Framework. You will find Singleton Properties (or fields) on classes that are meant to be instantiated only once. Think of a static Instance property as a global hook upon which to hang an object.
Can a Custom C# object contain a property of the same type as itself?
An object can indeed have a reference to an object of its own type.
This is how most Node
type objects are implemented.
As for instantiation - you can pass in the Employee
object to use as manager (passing in null for no manager). Constructors can have multiple overloads:
public Employee(Employee manager)
{
this.Manager = manager;
}
Define class with itself as generic implementation. Why/how does this work?的更多相关文章
- Why not inherit from List<T>?
问题: When planning out my programs, I often start with a chain of thought like so: A football team is ...
- c++ using Handle Class Pattern to accomplish implementation hiding
Reference material: Thinking In C++ 2nd eidition chapter 5 section "Handle classes" If the ...
- iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总
--系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...
- iOS--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook等系统服务开发汇总
iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用系统应用.使用系统服务: ...
- Three Sources of a Solid Object-Oriented Design
pingback :http://java.sys-con.com/node/84633?page=0,1 Object-oriented design is like an alloy consis ...
- DbUtils使用例子
DbUtils: JDBC Utility Component Examples This page provides examples that show how DbUtils may be us ...
- iOS开发系列通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开
--系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...
- 【转】 Build a RESTful Web service using Jersey and Apache Tomcat 2009
Build a RESTful Web service using Jersey and Apache Tomcat Yi Ming Huang with Dong Fei Wu, Qing GuoP ...
- IOS中调用系统的电话、短信、邮件、浏览功能
iOS开发系列--通讯录.蓝牙.内购.GameCenter.iCloud.Passbook系统服务开发汇总 2015-01-13 09:16 by KenshinCui, 26990 阅读, 35 评 ...
随机推荐
- 解决 UIView 设置背景为UIImage图片变型问题[XXX setBackgroundColor:[UIColor colorWithPatternImage:XXX]];
[self.drawingViewsetBackgroundColor:[UIColorcolorWithPatternImage:[selfthumbnailWithImageWithoutScal ...
- Codeforces Round #210 (Div. 1).B
经典的一道DP题. 题目明显是一道DP题,但是比赛的时候一个劲就在想怎么记录状态和转移.最后想到了一种n^3的方法,写了下,不出所料的超时了. 看了别人的代码才发现竟然是先二分然后再进行DP,像这种思 ...
- SDN开发过程中遇到的一些问题总结
我用的是ryu控制器,用Mininet作为网络系统平台. 当启动控制器的时候如果提示:unsupported version 0x1. if possible, set the switch to u ...
- iOS 错误提示
1.CUICatalog: Invalid asset name supplied: , or invalid scale factor: 2.000000 =>原因: You are call ...
- Less-mixin函数基础一
//mixin函数 立即执行mixin函数,example: .test{ color:#ff00000; background:red; } //立即执行mixin grammar 1 扩展exte ...
- mybatis循环map
一.循环key <foreach collection="map.keys" item="key" separator="and"&g ...
- Extjs3 combobox使用
Combobox 在程序中应用十分普遍,每个combobox的选项 一般对应两个值:一个用于前台显示的值,一个与显示值对应的value值.在后台获取value的值需使用combobox的 Hidden ...
- django的项目创建简明流程
个人理解,不妥之处请指出 创建项目:django-admin startproject user_sys 创建APP:python manage.py startapp auth 测试项目创建是否成功 ...
- 《CNI specification》翻译
Overview 本文提出了一个通用的基于插件的Linux容器网络解决方案,容器网络接口,CNI.它脱胎于旨在满足大多数rtk网络设计的rtk Networking Proposal. 首先,我们对如 ...
- CNI bridge 插件实现代码分析
对于每个CNI 插件在执行函数cmdAdd之前的操作是完全一样的,即从环境变量和标准输入内读取配置.这在http://www.cnblogs.com/YaoDD/p/6410725.html这篇博文里 ...