用五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树

这些对老一代的程序员都是老生常谈的东西,没什么新意,对新生代的程序员却充满着魅力。曾经新生代,好多都经过漫长的学习,理解,实践才能掌握委托,表达式树这些应用。今天我尝试用简单的方法叙述一下,让大家在五分钟内看完这篇博客。

第一分钟:委托

  有些教材,博客说到委托都会提到事件,虽然事件是委托的一个实例,但是为了理解起来更简单,今天只谈委托不谈事件。先上一段代码:

下边的代码,完成了一个委托应用的演示。一个委托分三个步骤:

public partial class WebForm3 : System.Web.UI.Page
{
    //step01:首先用delegate定义一个委托 。
    public delegate int CalculatorAdd(int x, int y);
    protected void Page_Load(object sender, EventArgs e)
    {
        //step03:用这个方法来实例化这个委托。
        CalculatorAdd cAdd = new CalculatorAdd(Add);
        //int result = cAdd(5, 6);
        int result = cAdd.Invoke(5,6);
    }
    // step02:声明一个方法来对应委托。
    public int Add(int x, int y)
    {
        return x + y;
    }
}

step01:首先用delegate定义一个委托?。

step02:声明一个方法来对应委托。

step03:用这个方法来实例化这个委托。

至此,一个委托的应该就完成了,就可以调用委托了。

第二分钟:匿名方法

  在上一分钟已经知道了,完成一个委托应用分三步走,缺一步都不行,如果要跨大步,当心步子大了扯着蛋。但是微软不怕扯着蛋,非要把三步做成两步来走啊!所以微软就用匿名方法来简化上边的三个步骤。匿名方法这个玩意儿怎么说呢,在C#中完全是可有可无的东西,只是为C#锦上添花,有人别出心裁给它取个名字叫语法糖。

public partial class WebForm3 : System.Web.UI.Page
{
    //step01:首先用delegate定义一个委托
    public delegate int CalculatorAdd(int x, int y);
    protected void Page_Load(object sender, EventArgs e)
    {
        //step02:用这样的写法 delegate(int x, int y) { return x + y; },把一个方法赋值给委托
        CalculatorAdd cAdd = delegate(int x, int y) { return x + y; };
        int result = cAdd.Invoke(5, 6);
    }
}

step01:首先用delegate定义一个委托 。

step02:用这样的写法 delegate(int x, int y) { return x + y; },把一个方法赋值给委托,其实这种写法就是匿名方法。

这时会惊奇的发现,这不是三步当着两步走了哇?

第三分钟:Lambda表达式

  原本很简单的程序,加上几个delegate关键字,这代码一下就变得深奥了,深奥的东西懂的人就变少了,所以这个还可以作为加薪的筹码。但是微软对C#的设计理念是简单易用。微软就想方设法的来简化delegate(int x, int y) { return x + y; }这个匿名方法,Lambda就出现了。下边我来看几种lambda表达式的写法:

public partial class WebForm3 : System.Web.UI.Page
{
    public delegate int CalculatorAdd(int x, int y);
    protected void Page_Load(object sender, EventArgs e)
    {
        //方法一:
        CalculatorAdd cAdd1 = (int x, int y) => { return x + y; };
        int result1 = cAdd1(5, 6);
        //方法二:
        CalculatorAdd cAdd2 = (x, y) => { return x + y; };
        int result2 = cAdd2(5, 6);
        //方法三:
        CalculatorAdd cAdd3 = (x, y) => x + y;
        int result3 = cAdd2(5, 6);
    }
}

方法一:简单的把delegate去掉,在()与{}之间加上? “=>”。

方法二:在方法一的基础上把参数类型都干掉了。

方法三:要干就干彻底些,把{},以及return关键字都去掉了。

这几种方法随便怎么写都行,不过就是害苦了初学者,一会儿看到这种写法,一会儿看到那种写法,把人搞的神魂颠倒人,如果没人指点,确实会迷糊,难就难在这儿。

第四分钟:泛型委托

  随着.net版本的不升级,新版本总要区别于旧版本吧,不然微软的工程师怎么向他们的老大交差呀?所以微软又来玩新花样了。

public partial class WebForm3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //方法一:
        Func cAdd1 = (int x, int y) => { return x + y; };
        int result1 = cAdd1(5, 6);
        //方法二:
        Func cAdd2 = (x, y) => { return x + y; };
        int result2 = cAdd2(5, 6);
        //方法三:
        Func cAdd3 = (x, y) => x + y;
        int result3 = cAdd2(5, 6);
    }
}

  不管是匿名方法还是Lambda表达式,完成一个委托的应用,都逃不过两个步骤,一步是定义一个委托,另一步是用一个方法来实例化一个委托。?微软干脆把这两步都合成一步来走了。用Func来简化一个委托的定义。

  至此一个委托的应用就可用? Func<int, int, int> cAdd3 = (x, y) => x + y;?这样一句话来完成了,其中的Func就是所谓的泛型委托。

第五分钟:表达式树

  表达式树其实与委托已经没什么关系了,非要扯上关系,那就这么说吧,表达式树是存放委托的容器。如果非要说的更专业一些,表达式树是存取Lambda表达式的一种数据结构。要用Lambda表达式的时候,直接从表达式中获取出来,Compile()就可以直接用了。如下代码:

public partial class WebForm3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Expression> exp = (x, y) => x + y;
        Func fun = exp.Compile();
        int result = fun(2, 3);
    }
}

  五分钟结束了,我点到的很肤浅,但至少让大家再温习了一篇委托,匿名方法,Lambda,泛型委托,表达式树

AngularJs分页pagination directive

html

<div ng-app="hello">
    <div ng-controller="pagingCtrl">
        <paging>
            <table class="table table-striped table-bordered table-hover">
                <tr>
                    <th>id</th>
                    <th>name</th>
                </tr>
                <tr ng-repeat="item in data">
                    <td>{{item.id}}</td>
                    <td>{{item.name}}</td>
                </tr>
            </table>
            <ul class="pagination" num-pages="tasks.pageCount" current-page="tasks.currentPage" on-select-page="selectPage(page)">
                <li ng-class="{disabled: noPrevious()}"> <a ng-click="selectPrevious()">&laquo;</a>
                </li>
                <li ng-repeat="page in pages" ng-class="{active: isActive(page)}"> <a ng-click="selectPage(page)">{{page}}</a>
                </li>
                <li ng-class="{disabled: noNext()}"> <a ng-click="selectNext()">&raquo;</a>
                </li>
            </ul>
        </paging>
    </div>
</div>

js

var myModule = angular.module('hello', []);
myModule.controller('pagingCtrl', function ($scope, $http) {
    $scope.data = [{
        id: 1,
        name: "a"
    }, {
        id: 2,
        name: "b"
    }];
    $scope.currentPage = 1;
    $scope.numPages = 5;
    $scope.pageSize = 10;
    $scope.pages = [];
    //get first page
    /*$http.get('url',
                {
                    method: 'GET',
                    params: {
                        'pageNo': $scope.currentPage,
                        'pageSize': $scope.pageSize
                    },
                    responseType: "json"
                }).then(function (result) {
                    $scope.data = result.data.Data;
                    $scope.numPages = Math.ceil(result.data.Total / result.data.PageSize);
                });*/
    $scope.onSelectPage = function (page) {
        //replace your real data
        /*$http.get('url',
                {
                    method: 'GET',
                    params: {
                        'pageNo': page,
                        'pageSize': $scope.pageSize
                    },
                    responseType: "json"
                }).then(function (result) {
                    $scope.data = result.data.Data;
                    $scope.numPages = Math.ceil(result.data.Total / result.data.PageSize);
                });*/
    };
});
myModule.directive('paging', function () {
    return {
        restrict: 'E',
        //scope: {
        //    numPages: '=',
        //    currentPage: '=',
        //    onSelectPage: '&'
        //},
        template: '',
        replace: true,
        link: function (scope, element, attrs) {
            scope.$watch('numPages', function (value) {
                scope.pages = [];
                for (var i = 1; i <= value; i++) {
                    scope.pages.push(i);
                }
                alert(scope.currentPage)
                if (scope.currentPage > value) {
                    scope.selectPage(value);
                }
            });
            scope.isActive = function (page) {
                return scope.currentPage === page;
            };
            scope.selectPage = function (page) {
                if (!scope.isActive(page)) {
                    scope.currentPage = page;
                    scope.onSelectPage(page);
                }
            };
            scope.selectPrevious = function () {
                if (!scope.noPrevious()) {
                    scope.selectPage(scope.currentPage - 1);
                }
            };
            scope.selectNext = function () {
                if (!scope.noNext()) {
                    scope.selectPage(scope.currentPage + 1);
                }
            };
            scope.noPrevious = function () {
                return scope.currentPage == 1;
            };
            scope.noNext = function () {
                return scope.currentPage == scope.numPages;
            };
        }
    };
});

jsfiddle

LINQ中.AsEnumerable() 和 .ToList() 的区别:

  • .AsEnumerable()延迟执行,不会立即执行。当你调用.AsEnumerable()的时候,实际上什么都没有发生。
  • .ToList()立即执行
  • 当你需要操作结果的时候,用.ToList(),否则,如果仅仅是用来查询不需要进一步使用结果集,并可以延迟执行,就用.AsEnumerable()/IEnumerable /IQueryable
  • .AsEnumerable()虽然延迟执行,但还是访问数据库,而.ToList()直接取得结果放在内存中。比如我们需要显示两个部门的员工时,部门可以先取出放置在List中,然后再依次取出各个部门的员工,这时访问的效率要高一些,因为不需要每次都访问数据库去取出部门。
  • IQueryable实现了IEnumberable接口。但IEnumerable 换成IQueryable后速度提高很多。原因:
    IQueryable接口与IEnumberable接口的区别: IEnumerable 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable 是将Skip ,take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。
  • IEnumerable跑的是Linq to Object,强制从数据库中读取所有数据到内存先。

使用viewport设置手机浏览器网页宽度

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
width:控制 viewport 的大小,可以指定的一个值,如果 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。
height:和 width 相对应,指定高度。
initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。
maximum-scale:允许用户缩放到的最大比例。
minimum-scale:允许用户缩放到的最小比例。
user-scalable:用户是否可以手动缩放

Copy and Paste is not working on my Remote Desktop Connection… what’s wrong?

A very annoying occurrence that I sometimes suffer is when all of a sudden the copy and paste function stops working when I am connected to a remote machine. Turns out the problem is coming from a little process called rdpclip. Rdpclip (remote desktop clipboard) is responsible for managing a shared clipboard between your local host and the remote desktop (the process runs on the remote machine not your local host).

So what do I do when clipboard stops working?

Luckily fixing the issue is pretty straightforward and involves a few simple steps.

  1. Load up task manager (right click taskbar and select Task Manager)
  2. Go to the Processes Tab
  3. Select rdpclip.exe
  4. Click End Process
  5. Go to the Application Tab
  6. Click New Process
  7. Type rdpclip
  8. Click Ok

There, copy and paste should now work normally again.

It happens so often, this process is annoying! What do I do to fix it permanently?

Unfortunately I don’t know why rdpclip stops working nor how to fix it permanently; however, there is a way to make it easier if it happens often.

  • Create a new bat file and call it whatever you want say, clipboard.bat.
  • Write the following two commands on separate lines in the new bat file
    • Taskkill.exe /im rdpclip.exe
    • Rdpclip.exe
    • Save the bat file and drag it into the toolbar quick launch section

Now whenever your copy and paste operation fails to restore it, all you need to do is click this new batch file which will kill rdpclip and restart it. Still a workaround but at least it’s a quick procedure.

– See more at: http://www.gfi.com/blog/copy-paste-working-remote-desktop-connection-whats-wrong/#sthash.AhDKFvk7.dpuf

C#从文件byte[]获取文件mime(contentType)

public class MimeHelper
    {
        public static int MimeSampleSize = 256;
        public static string DefaultMimeType = "application/octet-stream";
        [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
        private extern static System.UInt32 FindMimeFromData(
            System.UInt32 pBC,
            [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
            [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
            System.UInt32 cbSize,
            [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
            System.UInt32 dwMimeFlags,
            out System.UInt32 ppwzMimeOut,
            System.UInt32 dwReserverd
        );
        public static string GetMimeFromBytes(byte[] data)
        {
            try
            {
                uint mimeType;
                FindMimeFromData(0, null, data, (uint)MimeSampleSize, null, 0, out mimeType, 0);
                var mimePointer = new IntPtr(mimeType);
                var mime = Marshal.PtrToStringUni(mimePointer);
                Marshal.FreeCoTaskMem(mimePointer);
                return mime ?? DefaultMimeType;
            }
            catch
            {
                return DefaultMimeType;
            }
        }
    }