基础知识点汇聚

160 阅读2分钟

1 C# break 和 return的区别

break仅导致从循环退出,所以任何循环之后的语句都会执行。另一方面,return会导致从当前函数体中退出,所以函数体内的语句不会再执行。

所以,在触发语句之后你想要退出当前函数体,就用return;如果你想要继续在函数体中执行,使用break.

 public static void TestFor()
        {
            List<int> list = new List<int>();
            for (int i = 0; i < 5;i++ )
            {
                if (i == 2)
                {
                    continue;
                }
                list.Add(i);
            }

            Console.WriteLine(string.Format("数量:{0},值{1}",list.Count,string.Join(",",list))); //4个数字--0,1,3,4
        }
        public static void TestForBreak()
        {
            List<int> list = new List<int>();
            for (int i = 0; i < 5; i++)
            {
                if (i == 2)
                {
                    break;
                }
                list.Add(i);
            }

            Console.WriteLine(string.Format("数量:{0},值{1}", list.Count, string.Join(",", list)));//2个数字-- 0,1
        }

参考:www.cnblogs.com/chenlight/p…

2 C#中的值传递与引用传递(in、out、ref)

ref 引用传递可以理解为就是对象本身传递,而非一个副本或者地址,

值类型参数传递效果明显

引用类型参数效果看起来是一样的,没有ref 就是原来对象的内存地址,有就是原来的对象。

  public static void TestX(XDemo x) // 这里处理的还是原来的内存地址
        {
            //需要注意的是,如果值类型对象中含有引用类型的成员,那么当值类型对象在传递给方法时,副本中克隆的是引用类型成员的地址,而不是引用类型对象的副本,所以在方法中修改此引用类型对象成员中的成员等也会影响到原来的引用类型对象。
            x.Id = 10;
            x.Name = "测试数据";
        }
        public static void TestX2( ref XDemo x) //这个处理的是原来的对象地址
        {
            x.Id = 11;
            x.Name = "测试数据111";
        }
        public static void TestX3( XDemo x) //这里创建了新对象,不是原来的 ,所以不影响原来的值
        {
            //再看看引用类型对象,在值传递中,引用类型传递的是地址,在方法中可以通过这个地址去修改对象成员而影响到原对象的成员,但是无法影响到整个对象,看下面的例子: 
            //可以看到,Main方法中将myClass对象传入Invoke方法,在Invoke方法中给Invoke方法赋值,但是这并没有影响到Main方法中的myClass对象,这就好比,引用类型对象的数据保存在房间A中,作为方法参数传递时,会新建一个房间B,房间B保存的是房间A的地址,对房间B的任何修改会转向这个地址去修改,也就是房间A的修改,现在将房间B保存的地址换成房间C的地址,对房间B的操作自然跟房间A没有关系了。
            x = new XDemo() {Id=100,Name="dashuj" };
        }
        public static void TestX4(ref XDemo x) //这里引用的还是原来的对象,而不是地址,这就是说,在传递时,没有创建一个房间B,而是直接使用的房间A!(准确说,是给房间A取了一个别名)
        {
            x = new XDemo() { Id = 100, Name = "dashuj" };
        }

www.cnblogs.com/shanfeng100…

3 获取URL地址

假设当前页完整地址是:www.test.com/aaa/bbb.asp…

协议名----http:// 域名 ---- www.test.com 站点名---aaa 页面名(文件名) ----bbb.aspx 参数------id=5&name=kelli

3.1 完整url

1、完整url (协议名+域名+站点名+文件名+参数)
string url=Request.Url.ToString();
url= http://www.test.com/aaa/bbb.aspx?id=5&name=kelli

3.2 站点名+页面名+参数

2、站点名+页面名+参数
string url=Request.RawUrl;(或 string url=Request.Url.PathAndQuery;)
url= /aaa/bbb.aspx?id=5&name=kelli

3.3 站点名+页面名

3、站点名+页面名
string url=HttpContext.Current.Request.Url.AbsolutePath;
(或 string url= HttpContext.Current.Request.Path;)
url= aaa/bbb.aspx

3.4 域名

4、域名
string url=HttpContext.Current.Request.Url.Host;
url= www.test.com

3.5 参数

5、参数
string url= HttpContext.Current.Request.Url.Query;
url= ?id=5&name=kelli

参考:blog.csdn.net/CAO11021/ar…

绑定

   if (userInfo.IsBind)//绑定了才业务界面
                    {
                        if (!string.IsNullOrEmpty(oldBusinessUrl))
                        {
                            return Redirect(oldBusinessUrl);//跳转到业务链接
                        }
                    }
                   
                    return Redirect("/UserInfo/Index");//用户界面

3.6 获取网站协议

//获取应用程序名
string appName = HttpContext.Current.Request.ApplicationPath;

//获取协议名 http
string scheme=HttpContext.Current.Request.Url.Scheme;

//获取当前IP地址
string ip = HttpContext.Current.Request.Url.Host;

www.cnblogs.com/TheBob/p/93…

4 C# 中const和readonly的区别

const与readonly 很像,都是将变量声明为只读,且在变量初始化后就不可改写。那么,const与readonly 这两个修饰符到底区别在什么地方呢?其实,这个牵扯出C#语言中两种不同的常量类型:静态常量(compile-time constants)和动态常量(runtime constants)。这两者具有不同的特性,错误的使用不仅会损失效率,而且还会造成错误。

首先先解释下什么是静态常量以及什么是动态常量。静态常量是指编译器在编译时候会对常量进行解析,并将常量的值替换成初始化的那个值。而动态常量的值则是在运行的那一刻才获得的,编译器编译期间将其标示为只读常量,而不用常量的值代替,这样动态常量不必在声明的时候就初始化,而可以延迟到构造函数中初始化。

当你大致了解上面的两个概念的时候,那么就可以来说明const与readonly了。const修饰的常量是上述中的第一种,即静态常量;而readonly则是第二种,即动态常量。那么区别可以通过静态常量与动态常量的特性来说明:

(1) const修饰的常量在声明的时候必须初始化;readonly修饰的常量则可以延迟到构造函数初始化

(2) const修饰的常量在编译期间就被解析,即常量值被替换成初始化的值;readonly修饰的常量则延迟到运行的时候。 (const修饰的常量无法在VS中打断点调试,它的值在编译期间就确定了。VS中打断点调试是在运行期间)

此外const常量既可以声明在类中也可以在函数体内,但是static readonly常量只能声明在类中。

(3) const默认就是静态的,而readonly如果设置成静态的就必须显示声明。

(4) const修饰的值的类型也有限制,它只能为下列类型之一(或能够转换为下列类型):sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、string、enum类型或引用类型。注意能够声明为const的引用类型只能为string或值为null的其他引用类型。readonly可以是任何类型。

可能通过上述纯概念性的讲解,对有些初学者有些晕乎。下面就一些例子来说明下:

using System;
class P
{
    static readonly int A=B*10;
    static readonly int B=10;   
    public static void Main(string[] args)
    {
        Console.WriteLine("A is {0},B is {1} ",A,B);
    }
}

对于上述代码,输出结果是多少?很多人会认为是A is 100,B is 10吧!其实,正确的输出结果是A is 0,B is 10。好吧,如果改成下面的话:

using System;
class P
{
    const int A=B*10;
    const int B=10;   
    public static void Main(string[] args)
    {
        Console.WriteLine("A is {0},B is {1} ",A,B);
    }
}

对于上述代码,输出结果又是多少呢?难道是A is 0,B is 10?其实又错了,这次正确的输出结果是A is 100,B is 10。

那么为什么是这样的呢?其实在上面说了,const是静态常量,所以在编译的时候就将A与B的值确定下来了(即B变量时10,而A=B10=1010=100),那么Main函数中的输出当然是A is 100,B is 10啦。而static readonly则是动态常量,变量的值在编译期间不予以解析,所以开始都是默认值,像A与B都是int类型,故都是0。而在程序执行到A=B10;所以A=010=0,程序接着执行到B=10这句时候,才会真正的B的初值10赋给B。

参考:blog.csdn.net/weixin_4687…

5 C#中的async和await

下面这个 await 是同步,Result才是异步

  public static async void Test4()
        {
            Console.WriteLine("开始");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var t1 =await  add1();//这个使用是同步
            var t2 = await add2();
            var t3 =  await add3();
            Console.WriteLine(t1);//同步呀同步呀
            Console.WriteLine(t2);
            Console.WriteLine(t3); //还是同步呀
             //List<Task<int>> list = new List<Task<int>>();
             //list.Add(t1);
             //list.Add(t2);
             //list.Add(t3);
             //await Task.WhenAll(list).ContinueWith((t) =>
             //{
             //    Console.WriteLine( t1.Result);
             //    Console.WriteLine(t2.Result);
             //    Console.WriteLine(t3.Result);
             //});
            stopwatch.Stop();
            Console.WriteLine(string.Format("做早餐总计耗时:{0}", stopwatch.ElapsedMilliseconds));
            // Test3();
            Console.WriteLine("结束了");
        }
        public static void Test5()
        {
            Console.WriteLine("开始");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var t1 =  add1();//这个使用是异步
            var t2 =  add2();
            var t3 =  add3();
           
            Console.WriteLine(t1.Result);//这个是异步
            Console.WriteLine(t2.Result);//结果放到一起
            Console.WriteLine(t3.Result); //结果放到一起
            //List<Task<int>> list = new List<Task<int>>();
            //list.Add(t1);
            //list.Add(t2);
            //list.Add(t3);
            //await Task.WhenAll(list).ContinueWith((t) =>
            //{
            //    Console.WriteLine( t1.Result);
            //    Console.WriteLine(t2.Result);
            //    Console.WriteLine(t3.Result);
            //});
            stopwatch.Stop();
            Console.WriteLine(string.Format("做早餐总计耗时:{0}", stopwatch.ElapsedMilliseconds));
            // Test3();
            Console.WriteLine("结束了");
        }

        public static async Task<int> addaaaa1()
        {
            Thread.Sleep(6000);
            return 10;
        }

        public  static async Task<int> add1()
        {
            return await Task.Run(() =>
            {
                Thread.Sleep(6000);
                return 10;//返回的值必须是int 
            });
           
        }

        public static async Task<int> add2()
        {
            Task<int> t = new Task<int>(() => {
                Thread.Sleep(6000);
                return 100;
            });
            t.Start();
            return await t; //返回的值必须是int  https://www.jb51.net/article/216457.htm
        }

        public static async Task<int> add3() //编程异步
        {
            return await Task.Run(() =>
            {
                Thread.Sleep(6000);
                return 888;
            });  
        }

www.jb51.net/article/216…

而下面这个 await 是异步

      public static async void Test6()
        {
            Console.WriteLine("开始");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var t1 =  add1();//这个使用是同步
            var t2 =  add2();
            var t3 =  add3();
            Console.WriteLine(await t1);//同步呀同步呀
            Console.WriteLine(await t2);
            Console.WriteLine(await t3); //还是同步呀
            //List<Task<int>> list = new List<Task<int>>();
            //list.Add(t1);
            //list.Add(t2);
            //list.Add(t3);
            //await Task.WhenAll(list).ContinueWith((t) =>
            //{
            //    Console.WriteLine( t1.Result);
            //    Console.WriteLine(t2.Result);
            //    Console.WriteLine(t3.Result);
            //});
            stopwatch.Stop();
            Console.WriteLine(string.Format("做早餐总计耗时:{0}", stopwatch.ElapsedMilliseconds));
            // Test3();
            Console.WriteLine("结束了");
        }

根据上面两个例子可以得出,如果await 直接放到方法前面就是同步,放到中间变量前面就是异步。因此说是同步还是异步与他们所在位置有很大关系。调用的时候要特别留心。否则是同步,还以为是异步。

www.jb51.net/article/267…


        static public void TestWait8()
        {
            var t = Task.Run(async () =>
            {
                Console.WriteLine("Start");//后
                await Task.Delay(3000);
                Console.WriteLine("Done");//最后
            });
            Console.WriteLine("All done");//先
        }
        static public void TestWait8_5()
        {
            var t = Task.Factory.StartNew(async () =>
            {
                Console.WriteLine("Start");//先
                await Task.Delay(3000);
                Console.WriteLine("Done");//最后
            });
            t.Wait();
            Console.WriteLine("All done");//后
        }

        static public void TestWait8_6()
        {
            var t = Task.Run(async () =>
            {
                Console.WriteLine("Start");//先
                await Task.Delay(3000);
                Console.WriteLine("Done");//后
            });
            t.Wait();
            Console.WriteLine("All done");//最后
        }

        static public void TestWait()
        {
            var t = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Start");//先
                Task.Delay(3000).Wait();
                Console.WriteLine("Done");//后
            });
            t.Wait();
            Console.WriteLine("All done");//最后
        }

        static public void TestWait2()
        {
            var t = Task.Factory.StartNew(async () =>
            {
                Console.WriteLine("son:" + Thread.CurrentThread.ManagedThreadId.ToString());
                Console.WriteLine("Start");//先
                await Task.Delay(3000);
                Console.WriteLine("Done");//最后
                Console.WriteLine("son:" + Thread.CurrentThread.ManagedThreadId.ToString());
            });
            t.Wait();
            Console.WriteLine("All done");//后
            Console.WriteLine("main:" + Thread.CurrentThread.ManagedThreadId.ToString());
        }

        static public void TestWait3()
        {
            var t = Task.Run(async () =>
            {
                Console.WriteLine("son:" + Thread.CurrentThread.ManagedThreadId.ToString());
                Console.WriteLine("Start");//先
                await Task.Delay(3000);
                Console.WriteLine("son:" + Thread.CurrentThread.ManagedThreadId.ToString());
                Console.WriteLine("Done");//后
            });
            t.Wait();
            Console.WriteLine("All done");//最后
            Console.WriteLine("main:" + Thread.CurrentThread.ManagedThreadId.ToString());
        }

执行

    Console.WriteLine("Main :" + Thread.CurrentThread.ManagedThreadId.ToString());
            TestWait2();
            Task.Delay(5000).Wait();
            Console.ReadKey();