.NET Framework基础知识(三)(转载)
1、正则表达式:用一串字符验证是否符合一种规范,这个规范就是正则表达式。
2、正则表达式中常用的元字符:
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
例: string regstr = @"^\d\d\d$";
Regex reg = new Regex(regstr);
string intputstr = "163";
if (reg.IsMatch(intputstr))
{
Console.WriteLine("正确");
}
else
{
Console.WriteLine("错误");
}
注意:添加命名空间
3、正则表达式中的转义字符:
一般字符 除.$^{}[(|)*+?\外,其他字符与自身匹配
\a 与响铃匹配
\b 转义字符\b是一个特例。在正则表达式中,\b表示单词边界(在\w和\W之间),不过,在[]字符类中,\b表示退格符。
在替换模式中,\b始终表示退格符。
\t 与Tab符匹配
\r 与回车符匹配
\v 与垂直符匹配
\f 与换页符匹配
\n 与换行符匹配
\e 与Esc符匹配
\ 在后面带有不识别为转义字符时,与该字符匹配
例:string regstr = @"^0\d{2}-\d{8}$";
Regex reg = new Regex(regstr);
string intputstr = "010-99999999";
if (reg.IsMatch(intputstr))
{
Console.WriteLine("正确");
}
else
{
Console.WriteLine("错误");
}
4、正则表达式中的重复:
* 重复零次或更多次
+ 重复一次或更多次
? 重复一次或零次
{n} 重复n次
{n,}重复n次或更多次
{n,m}重复n到m次,m不能小于n
5、字符类:
[abcde]匹配a,b,c,d,e中的任一个字符
[0-9]含义与\d相同,匹配任意数字
[a-z0-9A-Z]含义与\w相同,匹配数字,字母,下划线
例:电话号码的验证
string regstr = @"^\(?0\d{2}[) -]?\d{8}$";
Regex reg = new Regex(regstr);
string intputstr = "010-22222222";
if (reg.IsMatch(intputstr))
{
Console.WriteLine("正确");
}
else
{
Console.WriteLine("错误");
}
说明:^开始标记
\(?表示(可出现0次和一次
0表示本身
\d{2}表示数字出现两次
[) -]?表示在),空格,-中的一个字符出现0次或一次
\d{8}8个数字
$结束标记
6、分支条件:指有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。
例:电话号码验证
string regstr = @"^\(0\d{2}\)[- ]?\d{8}$|^0\d{2}[- ]?\d{8}$";
Regex reg = new Regex(regstr);
string intputstr = "(010)-22222222";
if (reg.IsMatch(intputstr))
{
Console.WriteLine("正确");
}
else
{
Console.WriteLine("错误");
}
说明:条件的匹配是从左到右的,第一个匹配成功,就不再匹配第二个条件。
^\(0\d{2}\)[- ]?\d{8}$|^匹配(010)-22222222或(010) 22222222
^0\d{2}[- ]?\d{8}$匹配010-22222222或010 22222222
7、分组表达式:单个字符的重复可以用限定符来实现,比如\d?是一个整数出现一次或不出现
string regstr = @"^(([01]?\d\d?|2[0-4]\d|25[0-5])\.){3}([01]?\d\d?|2[0-4]\d|25[0-5])$";
Regex reg = new Regex(regstr);
string intputstr = "001.020.030.040";
if (reg.IsMatch(intputstr))
{
Console.WriteLine("正确");
}
else
{
Console.WriteLine("错误");
}
说明:IP地址是0到255每个段,前三节数字后都有一个“.”所以可以分组。这个三个数字中,百位只能是0,1,2,
当是0或1时,十位,个位什么数字都可以,当百位为2时,十位不能超过5,当十为5时,个位不能超过5,所以可以这样分组,
当百位为0和1时分一组,当百位为2时,十位为5时分一组,当百位为2,十位为0到4时,个位什么都可以分一组,共三组。
8、反义:
\W 匹配任意不是字母,数字下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou]匹配除了aeiou这几个字母以外的任意字符
9、后向引用:如果有分组的话,每个分组会自动有一个组号,从|开始连续排下来,也可以给组来命名代替组号。
例:string regstr = @”^(\d)(-)\1\2$”; //可以用命名来代替string regstr = @“^(?<gsw>\d)(-)\k<gsw>\1$”;
如果第一个组用命名,第二个的组号从1开始。也可以把<>换成’
Regex reg = new Regex(regstr);
string intputstr = "1-1-";
if (reg.IsMatch(intputstr))
{
Console.WriteLine("正确");
}
else
{
Console.WriteLine("错误");
}
说明:给组命名格式为:(?<组名>或(?’组名’
后向引有时用\k<组名>或 \k’组名’
10、零宽断言:在某个位职,判断是否满足一定条件
(1)零宽度正预测先行断言:断言自身出现的位置的后面能匹配表达式
例:static void Main(string[] args)
{
string regstr = @"\b\w+(?=ing\b)";
Regex reg = new Regex(regstr);
string intputstr = "this eating jumping";
Match mat = reg.Match(intputstr);
Print(mat);
}
static void Print(Match match)
{
if (match.Value != "")
{
Console.WriteLine("匹配值:{0},匹配位置:{1}", match.Value, match.Index);
Print(match .NextMatch());
}
}
说明:?=匹配以ing结尾的单词
(2)零宽度正回顾后发断言:断言自身出现的位置的前面能匹配表达式
例:static void Main(string[] args)
{
string regstr = @"(?<=<(a)\s.*>).*(?=<\/\1>)";
Regex reg = new Regex(regstr);
string intputstr = "<a href='http://cn.bing.com'>必应</a>";
Match mat = reg.Match(intputstr);
Print(mat);
}
static void Print(Match match)
{
if (match.Value != "")
{
Console.WriteLine("匹配值:{0},匹配位置:{1}", match.Value, match.Index);
Print(match .NextMatch());
}
}}
说明:?<=匹配以<a >开头以</a>结尾的标签
(3)零宽度负预测先行断言:断言此位置的后面不能匹配表达式
例: static void Main(string[] args)
{
string regstr = @"\b\w*th(?!a)\w*\b";
Regex reg = new Regex(regstr);
string intputstr = "this toothache tooth";
Match mat = reg.Match(intputstr);
Print(mat);
}
static void Print(Match match)
{
if (match.Value != "")
{
Console.WriteLine("匹配值:{0},匹配位置:{1}", match.Value, match.Index);
Print(match .NextMatch());
}
}
说明:?!匹配以非表达式的单词
(4)零宽度负回顾后发断言:断言此位置前面不能匹配表达式
例:static void Main(string[] args)
{
string regstr = @"\b\w*(?<!a)th\w*\b";
Regex reg = new Regex(regstr);
string intputstr = "this toothache tooth";
Match mat = reg.Match(intputstr);
Print(mat);
}
static void Print(Match match)
{
if (match.Value != "")
{
Console.WriteLine("匹配值:{0},匹配位置:{1}", match.Value, match.Index);
Print(match .NextMatch());
}
}
说明:?<!匹配以非表达式的单词
11、注释:?#注释内容
注意:注释不能加到一个表达式之间
12、后向引用的分类如图:
13、精确匹配与模糊匹配:模糊匹配是以从开头到结尾,精确匹配是一个离开始最近的结尾字符匹配
*? 重复任意次,但尽可能少重复
+? 重复一次或更多次,但尽可能少重复
?? 重复0次或一次,但尽量少重复
{n,m} 重复n到m次,但尽量少重复
{n,} 重复n次以上,但尽量少重复
例:static void Main(string[] args)
{
string regstr = @”\bt.*s\b”;//模糊匹配,@“\bt.*?s\b”;精确匹配
Regex reg = new Regex(regstr);
string intputstr = “Children eat lunch at an orphanage being used by the U.N. children
‘s agency UNICEF for Haitian children separated from parents after last month’s earthquake”;
Match mat = reg.Match(intputstr);
Print(mat);
}
static void Print(Match match)
{
if (match.Value != "")
{
Console.WriteLine("匹配值:{0},匹配位置:{1}", match.Value, match.Index);
Print(match .NextMatch());
}
}
14、泛型
(1)使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
(2)泛型最常见的用途是创建集合类。
(3).NET Framework 类库在 System.Collections.Generic 命名空间中包含几个新的泛型集合类。
应尽可能地使用这些类来代替普通的类,如 System.Collections 命名空间中的 ArrayList。
(4)您可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。
(5)可以对泛型类进行约束以访问特定数据类型的方法。
(6)关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取。
类型参数命名准则:
(1)务必使用描述性名称命名泛型类型参数
(2)考虑使用T作为具有单个字母类型参数的类型的类型参数名
(3)务必将T作为描述性类型参数名的前缀
(4)考虑在参数名中指示对此类型参数的约束
泛型方法:
static void Main(string[] args)
{
PrintType<int>(5);
PrintType<bool>(true);
PrintType<string>("泛型真伟大");
PrintType(1.2); //省略类型参数,编译器会自动推导出是double类型,这里要注意,
编译器是根据参数的类型推导出类型参数的,如果方法没有参数,编译器是无法推导出来的。
}
static void PrintType<T>(T i)
{
Console.WriteLine("类型:{0,-20} 值:{1}",i.GetType (),i);
}
说明:此时的泛型方法,有点类似于方法重载中参数类型不同,个数相同的情况,如果用泛型实现,大大减少了代码。
15、泛型约束:在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。
如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。约束是用where上下文关键字指定的。
下面是几种约束的类型:
(1)T:结构 类型参数必须是值类型。可以指定除以外的任何值类型。
(2)T:类 类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
(3)T:new() 类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
(4)T:<基类名> 类型参数必须是指定的基类或派生自指定的基类。
(5)T:<接口名称> 类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。
(6)T:U 为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。
例1:
T:结构
类型参数必须是值类型。
static void Main(string[] args)
{
PrintType<int>(5); //正确的写法
PrintType<string>(“泛型真伟大”); //错误的写法
}
static void PrintType<T>(T i) where T: struct
{
Console.WriteLine("类型:{0,-20} 值:{1}",i.GetType (),i);
}
例2:
T:类
类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
static void Main(string[] args)
{
PrintType<int>(5); //错误的写法
PrintType<string>(“泛型真伟大”); //正确的写法
}
static void PrintType<T>(T i) where T: class
{
Console.WriteLine("类型:{0,-20} 值:{1}",i.GetType (),i);
}
例3:
T:new()
类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。
class Program
{
static void Main(string[] args)
{
PrintType<Demo>(new Demo());
}
static void PrintType<T>(T i) where T: new()
{
Console.WriteLine("类型:{0,-20} 值:{1}",i.GetType (),i);
}
}
class Demo
{
}
例4:
T:<基类名>
类型参数必须是指定的基类或派生自指定的基类。
class Program
{
static void Main(string[] args)
{
PrintType<Demo>(new Demo1()); //正确
PrintType<Demo>(new Demo()); //正确
PrintType<Demo1>(new Demo1()); //正确
PrintType<Demo2>(new Demo2()); //错误
}
static void PrintType<T>(T i) where T:Demo
{
Console.WriteLine("类型:{0,-20} 值:{1}",i.GetType (),i);
}
}
class Demo
{}
class Demo1 : Demo
{}
class Demo2
{}
例5:
T:<接口名称>
类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。
class Program
{
static void Main(string[] args)
{
PrintType<IDemo>(new Demo()); //正确
PrintType<Demo>(new Demo()); //正确
}
static void PrintType<T>(T i) where T : IDemo
{
Console.WriteLine("类型:{0,-20} 值:{1}", i.GetType(), i);
}
}
interface IDemo
{ }
class Demo : IDemo
{ }
例6:
T:U
为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。
class Program
{
static void Main(string[] args)
{
PrintType<IDemo,Demo>(new Demo()); //错误
PrintType<Demo,IDemo>(new Demo()); //正确
PrintType<Demo, Demo>(new Demo()); //正确
}
static void PrintType<T,U>(T i) where T : U
{
Console.WriteLine("类型:{0,-20} 值:{1}", i.GetType(), i);
}
}
interface IDemo
{ }
class Demo : IDemo
{ }
也可以对同一类型参数应用多个约束,并且约束自身可以是泛型类型
如下所示:
static void PrintType<T>(T i) where T : class ,new ()
{
Console.WriteLine("类型:{0,-20} 值:{1}", i.GetType(), i);
}
16、泛型类:泛型类封装不是特定于具体数据类型的操作。泛型类最常用于集合,如链接列表、哈希表、堆栈、队列、树等。
像从集合中添加和移除项这样的操作都以大体上相同的方式执行,与所存储数据的类型无关。一般情况下,创建泛型类的过程为:
从一个现有的具体类开始,逐一将每个类型更改为类型参数,直至达到通用化和可用性的最佳平衡。
创建自己的泛型类时应注意:
(1)将哪些类型通用化为类型参数。
(2)通常,能够参数化的类型越多,代码就会变得越灵活,重用性就越好。但是,太多的通用化会使其他开发人员难以阅读或理解代码。
(3)如果存在约束,应对类型参数应用什么约束。一条有用的规则是,应用尽可能最多的约束,但仍使您能够处理必须处理的类型。
例如,如果您知道您的泛型类仅用于引用类型,则应用类约束。这可以防止您的类被意外地用于值类型,并允许您对 T 使用 as 运算符以及检查空值。
(4)是否将泛型行为分解为基类和子类。由于泛型类可以作为基类使用,此处适用的设计注意事项与非泛型类相同。
(5)是否实现一个或多个泛型接口。
17、default:此关键字对于引用类型会返回 null,对于数值类型会返回零。对于结构,此关键字将返回初始化为零或
null 的每个结构成员,具体取决于这些结构是值类型还是引用类型
18、程序:定义一个自己的泛型类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Day1302
{
class Program
{
static void Main(string[] args)
{
MyList<int> list = new MyList<int>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.remove(3);
foreach(int i in list)
{
Console.WriteLine(i);
}
}
}
class MyList<T> : IEnumerable
{
T[] t = new T[0];
int count;
public int Count
{
get
{
return count;
}
}
public T this[int index]
{
get
{
if (index > count)
{
throw new Exception("超出索引!");
}
else
{
return t[index];
}
}
set
{
if (index < count)
{
t[index] = value;
}
else
{
throw new Exception("超出索引!");
}
}
}
public MyList()
{ }
public MyList(int capacipy)
{
t=new T[capacipy];
}
public int Capacipy
{
get
{
return t.Length;
}
set
{
if (value < count)
{
throw new Exception("容量小于元素个数!");
}
else
{
T[] t1=new T[value];
for (int i = 0; i < count; i++)
{
t1[i]=t[i];
}
t1 = t;
}
}
}
/// <summary>
/// 添加
/// </summary>
/// <param name="t2"></param>
/// <returns></returns>
public int add(T t2)
{
if (t.Length == 0)
{
t = new T[4];
t[0] = t2;
count++;
return 0;
}
else if (count < t.Length)
{
t[count] = t2;
count++;
return count - 1;
}
else
{
T[] t3=new T[t.Length*2];
for (int i = 0; i < count; i++)
{
t3[i] = t[i];
}
t3[count] = t2;
count++;
t = t3;
return count - 1;
}
}
/// <summary>
/// 移除元素
/// </summary>
/// <param name="t2"></param>
public void remove(T t2)
{
int index = -1;
for (int i = 0; i < count; i++)
{
if (t[i].Equals(t2))
{
index = i;
}
}
if (index != -1)
{
for (int i = index; i < count-1; i++)
{
t[i] = t[i + 1];
}
t[count-1]=default(T);
count--;
}
}
public IEnumerator GetEnumerator()
{
for (int i = 0; i < count; i++)
{
yield return t[i];
}
}
}
}
本文出自 “大懒丫头” 博客,请务必保留此出处http://lanyatou.blog.51cto.com/3306130/625828
出处:http://www.cnblogs.com/babycool/
本文首发博客园,版权归作者跟博客园共有。
转载必须保留本段声明,并在页面显著位置给出本文链接,否则保留追究法律责任的权利。