存档

2016年10月 的存档

C# 的常见误区整理

2016年10月11日 没有评论
C# 的常见误区整理



本文为《编写高质量的代码:改善C#程序的157个建议》中整理出来对我有用的知识,算是读书笔记吧。所以并不全,有兴趣了解详情的童鞋可以去买纸质书一探究竟。

  1. 当容易出错时,使用TryParse会更高效。
  2. 使用?可以对一个值类型赋空值,这种算符对应的基类为Nullable<T>。使用??可以对其是否为空进行简化判断,因此可以这样写:
int? i = 123;
int j = i ?? 0;

//等价于
int? i = 123;
int j;
if(i.HasValue)
{
    j = i.Value;
}
else 
{
    j = 0;
}
  1. const是编译期常量,所以效率比readonly高。
  2. 不要手动为枚举赋值,因为它的值是可重复的。
  3. 让一个类继承IComparable<T>接口,当把它的实例放到集合中时,直接调用Sort方法,就可以按规则排序。虽然我还是喜欢用Lambda单写排序…
  4. 深拷贝不一定非要一个个手动复制变量,也可以采用内存复制的形式:
public Employee DeepClone()
{
    using(Stream objectStream = new MemoryStream())
    {
        IFormatter formatter = new BinaryForamtter();
        formatter.Serialize(objectStream, this);
        objectStream.Seek(0,SeekOrigin.Begin);
        return formatter.Deserialize(objectStream) as Employee;
    }
}
  1. C#集合的分类:
    C# 的常见误区整理
  2. System.Collections.Concurrent命名空间下有线程安全的集合类。
  3. 为了防止公开变量的写入,可以为其添加一个带参数的构造方法,然后把它设为对外只读。
  4. 一般说来,使用Action、Func等预定义好的委托就足够了,没必要自己定义委托。还有些其他用途的,比如EventHandler、AsyncCallback等会作为一些接口参数出现,但本质是一样的。可以在MSDN页面上搜委托,然后在左侧的导航列表中就能看到所有的类型了。
  5. 所有的委托都应封装成事件,大多数情况是不需要自定义委托类型的。例如下面的代码,就是使用了EventHandler:
class FileUploadedEventArgs : EventArgs
{
    public int FileProgress {get;set;}
}

class FileUploader
{
    public  event EventHandler<FileUploadedEventArgs> FileUploaded;

    public void Upload()
    {
        FileUploadedEventArgs e = new 
                        FileUploadedEventArgs() { FileProgress = 100};
        while(e.FileProgress > 0)
        {
            //Up Load File
            e.FileProgress--;
            if(FileUploaded != null)
            {
                FileUploaded(this,e);
            }
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        FileUploader fl = new FileUploader();
        fl.FileUploaded +=Progress;
        fl.Upload();
    }

    static void Progress(object sender,FileUploadedEventArgs e)
    {
        Console.writeLine(e.FileProgress);
    }

}
  1. 委托命名建议采用动词或形容词。对于使用+=注册的事件处理器,使用"事件变量所属对象+下划线+事件变量名"来命名,委托或委托中间的回调应按照”委托变量所属对象+On+事件来源+委托变量名”为命名规则,例如:
public Main()
{
    Button btn = new Button();
    btn.Click+= new EventHandler(button_Click);
}

void button_Click(object sender,EventArgs e)
{
}

void SalaryOnEmployeeChanged(object sender,EventArgs e)
{

}

如果你觉得这篇文章对你有帮助,可以顺手点个,不但不会喜当爹,还能让更多人能看到它… C# 的常见误区整理

分类: 未分类 标签:

Unity3d开发(十七)UGUI 事件体系分析

2016年10月10日 没有评论
Unity3d开发(十七)UGUI 事件体系分析



很多Unity3D项目都使用了UGUI,但并不是所有人都研究过它的内部结构。由于准备定制自己的UI,不弄明白它内部的机制有点说不过去呢。这篇文章主要分析一下它的事件体系结构,以及点击事件的逻辑流程。本篇文章依托于UGUI的源码,如何获取UGUI的源码可以参考Unity3d(十六) 重写UGUI组件

事件体系

事件体系总体上说由四部分组成,分别是:监测器,派发器,采集器,响应器。

监测器指的是EventSystem类,它重写了MonoBehavior的Update方法,会在每一帧更新挂载在同一个GameObject上的BaseInputModule组件状态,并判断是否应该激活Module,如果是,则去调用各个Module的Process。

派发器指的就是BaseInputModule,最常用的是它的子类StandaloneInputMoudle。它完成了实际的事件生成。包括且不限于:事件类型的确定,事件数据的收集,派发对象的过滤。其中对派发对象的获取需要借助采集器,但需要通过监测器来获取,这种设计可以带来效率上的优势,虽然实现时并没有相关的代码。

采集器是指BaseRaycaster,在UGUI中使用的是其子类GraphicRaycaster。当事件发生时,会由Module请求一个射线点触,返回所有能点到的物体并返回,交由派发器进行过滤。它有一个内部的管理类RaycasterManager,用来做链接采集器和监测器的单向桥梁。

响应器是指IEventSystemHandler及其子类,例如最常用的IPointerClickHandler,它处理的是点击事件。通过ExecuteEvents类,可以将发生事件的对象上所有的响应器都获取到并调用其响应逻辑。以点击为例,事件最终会被派发到OnClick的代理上。完成逻辑的执行。

这四个模块大致的依赖关系如下: 

Unity3d开发(十七)UGUI 事件体系分析

类图

类有好多,但相比于流程要简单不少。类分两部分,一部分是功能类,一部分是编辑器类。

功能类按照上一节的事件体系可以清晰的找到重要的基类,UML图如下:

Unity3d开发(十七)UGUI 事件体系分析

这个图只是和点击相关的部分,当然还有很多其他的功能例如拖拽,滑动等等。但如果能找到这些重点,其他分支逻辑相信大家分分钟都能看懂了。

另一类是编辑器类,这个比较简单,我就没单独梳理类图,直接用VS自动生成的类图就够用了:

Unity3d开发(十七)UGUI 事件体系分析

你若是觉得这些编辑器类没什么用,那你一定是对编辑器代码理解还不深。UGUI的编辑器界面还算获得了广泛的好评,当需要自定义Inspector界面时,一些功能一定用得上,如果有空我也准备深入研究一下。

点击的逻辑流程

下面基于事件体系的划分,针对一次按钮点击梳理一下调用逻辑,流程图如下:

Unity3d开发(十七)UGUI 事件体系分析

总结

“动手改之前,要先弄明白别人的程序逻辑”。说起来很简单,但又有几个人能坚持做好呢?虽然我也是在外层包装了各种控件之后,才下决心重写UGUI Unity3d开发(十七)UGUI 事件体系分析 。 看到现在这种程度可真心花了不少时间,整理出来希望对大家有帮助 Unity3d开发(十七)UGUI 事件体系分析

如果你觉得这篇文章对你有帮助,可以顺手点个,不但不会喜当爹,还能让更多人能看到它… Unity3d开发(十七)UGUI 事件体系分析

分类: 未分类 标签: