C#总结之高级语法

C#高级语法

接着上一篇《C#总结之泛型》,来继续总结C#语法,这篇主要汇总C#高级语法的用法,包括特性,初始化器,推理类型,匿名类型,动态查找,以及Lambda表达式,扩展方法,反射等用法。

1. 特性

特性可以为代码标记一些可以被外部读取的信息,通过这种方式来影响我们所定义类型的使用方式。

// 应用的目标类型:类,属性,或者其他,是否对同一个目标进行多次应用
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
class DoesInterestingThingsAttribute : Attribute
{
	public int HowManyTimes { get; private set; }
	public string WhatDoesItDo { get; set; }

	public DoesInterestingThingsAttribute(int howManyTimes)
	{
		HowManyTimes = howManyTimes;
	}
}

[DoesInterestingThings(1000,WhatDoesItDo ="dahlin")]
public class DecoratedClass {}

static void Main(string[] args)
{
	Type classType = typeof(DecoratedClass);
	object[] customAttributes = classType.GetCustomAttributes(true);
	foreach(object customAttribute in customAttributes)
	{
		WriteLine($"Attribute of type {customAttribute} found.");
		DoesInterestingThingsAttribute interestingThingsAttribute = 
		customAttribute as DoesInterestingThingsAttribute;
		if (interestingThingsAttribute != null)
		{
			WriteLine($"This class does {interestingThingsAttribute.WhatDoesItDo} x
			 {interestingThingsAttribute.HowManyTimes}");
		}
	}

	ReadKey();
}

2. 初始化器

// 对象初始化器
Animal animal = new Animal
{
	Name = "Rual",
	Age = 12,
	Weight = 145.2,
	Origin = new Farm
	{
		Name = "Circle Perk",
		Location = "Ann Road",
		Rating = 15
	}
};

// 集合初始化器
List<int> myIntCollection = new List<int> { 5, 6, 5, 10, 22, 99 };
List<Animal> moreAnimals = new List<Animal>
{
	new Animal
	{
		Name="cow",
		Age=3,
		Weight=113
	},
	new Animal
	{
		Name="chicken",
		Age=1,
		Weight=12
	},
};

public class Animal
{
	public string Name { get; set; }
	public int Age { get; set; }
	public double Weight { get; set; }
	public Farm Origin { get; set; }
}

public class Farm
{
	public string Name { get; set; }
	public string Location { get; set; }
	public int Rating { get; set; }

}

3. 类型推理

var myVar = 5;
var myIntArray = new[] { 1, 2, 3, 4 };
var myArray = new int?[] { 4, null, 6, 8, 6, };

4. 匿名类型

var animals = new[]
{
	new {Name="Benjamin",Age=33,Weight=12},
	new {Name="Benjamin",Age=33,Weight=12},
	new {Name="Mike",Age=22,Weight=32}
};
WriteLine(animals[0].ToString());
WriteLine(animals[0].GetHashCode());
WriteLine(animals[1].GetHashCode());
WriteLine(animals[2].GetHashCode());
WriteLine(animals[0].Equals(animals[1]));
WriteLine(animals[0].Equals(animals[2]));
WriteLine(animals[0]==animals[1]);
WriteLine(animals[0]==animals[2]);

5. 动态查找

动态查找功能由Dynamic Language Runtime,动态语言运行库,DLR支持。C# 4引入dynamic关键字,以用于定义变量。

class MyClass1
{
public int Add(int var1, int var2) => var1 + var2;
}
class MyClass2 { }

class Program
{

	static int callCount = 0;
	static dynamic GetValue()
	{
		if (callCount++ == 0)
		{
			return new MyClass1();
		}
		return new MyClass2();
	}

static void Main(string[] args)
{
	try
	{
		dynamic firstResult = GetValue();
		dynamic secondResult = GetValue();
		WriteLine($"firstResult is:{firstResult.ToString()}");
		WriteLine($"SecondResult is:{secondResult.ToString()}");
		WriteLine($"firstResult call:{firstResult.Add(2,3)}");
		WriteLine($"secondResult call:{secondResult.Add(2, 3)}");
	}
	catch(RuntimeBinderException ex)
	{
		WriteLine(ex.Message);
	}
	ReadKey();
}

6.Lambda表达式

Lambda表达式由3个部分组成,放在括号里的未类型化的参数,=>运算符,C#语句

  • 表达式参数可以声明类型,如:(int paramA,int paramB)=>paramA+paramB
    单个参数时省略括号,如:param1=param1*param2
    没有参数时,()=>Math.PI;
  • 表达式语句体可以使用返回值:(a,b)=>{return value};
  • Lambda表达式委托:
    Action,Action<>,Func<> 其中 Func<>中最后一个参数始终是返回值类型
delegate int TwoIntegerOperationDelegate(int paramA, int paramB);

class Program
{
/// <summary>
/// 主入口函数
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
	WriteLine("f(a,b)=a+b");
	PerformOperations((a, b) => a + b);
	WriteLine("f(a,b)=a*b");
	PerformOperations((a, b) => a * b);
	WriteLine("f(a,b)=(a-b)%b");
	PerformOperations((a, b) => (a-b)%b);
	ReadKey();
}

static void PerformOperations(TwoIntegerOperationDelegate del)
{
	for(int paramAVal = 1; paramAVal <= 5; paramAVal++)
	{
		for(int paramBVal = 1; paramBVal <= 5; paramBVal++)
		{
			int delegateCallResult = del(paramAVal, paramBVal);
			Write($"f({paramAVal},{paramBVal})={delegateCallResult}");
			if (paramBVal != 5)
			{
				Write(",");
			}
		}
		WriteLine();
	}
}

7. 扩展方法

扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。 扩展方法当然不能破坏面向对象封装的概念,所以只能是访问所扩展类的public成员。
扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。
C#扩展方法第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。
扩展方法的目的就是为一个现有类型添加一个方法,现有类型既可以是int,string等数据类型,也可以是自定义的数据类型。


static void Main(string[] args)
{
	string strTest = null;
	// 调用扩展方法
	var strResult = strTest.GetNotNullStr();
	WriteLine(strResult);

	Person person = new Person();
	person.Age = 20;
	// 调用自定义类的扩展方法
	var isChild = person.GetBIsChild();
	WriteLine(isChild);

	ReadKey();
}

// 扩展方法
public static class MyString
{
	public static string GetNotNullStr(this string strRes)
	{
		if (strRes == null)
			return string.Empty;
		else
			return strRes;
	}
}

public class Person
{
	public string Name { set; get; }
	public int Age { set; get; }
}

// 自定义类的扩展方法
public static class MyPerson
{
	public static bool GetBIsChild(this Person oPerson)
	{
		if (oPerson.Age >= 18)
			return false;
		else
			return true;
	}
}

注意事项:

  • (1)扩展方法不能和调用的方法放到同一个类中
  • (2)第一个参数必须要,并且必须是this,这是扩展方法的标识
    如果方法里面还要传入其他参数,可以在后面追加参数
  • (3)扩展方法所在的类必须是静态类
  • (4)最好保证扩展方法和调用方法在同一个命名空间下

8. 反射

Reflection,中文翻译为反射。这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:程序集(Assembly)、模块(Module)、类型(class)组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息,例如:

  • Assembly类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。
  • Type类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过Type类可以得到这些要素的信息,并且调用之。
  • MethodInfo包含方法的信息,通过这个类可以得到方法的名称、参数、返回值等,并且可以调用之。
  • 诸如此类,还有FieldInfo、EventInfo等等,这些类都包含在System.Reflection命名空间下。
8.1 使用反射获取类型
public  void  Process(  object  processObj  )
{
Type  t  =  processsObj.GetType();
if(t.GetInterface("ITest")!=null  ){}
}

Type  t  =  Type.GetType(“System.String”);

Type  t  =  Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0,  Culture=neutral,  PublicKeyToken=b77a5c561934e089");

8.2 根据类型来动态创建对象

Type  t  =  Type.GetType("System.Data.DataTable,System.Data,Version=1.0.3300.0,  Culture=neutral,  PublicKeyToken=b77a5c561934e089");
DataTable  table  =  (DataTable)Activator.CreateInstance(t);

// 根据有参数的构造器创建对象
// 把参数按照顺序放入一个Object数组中即可
public class TestClass
	{

		private string _value;
		public TestClass(){}
		public TestClass(string value)
		{
			_value = value;
		}

		public string GetValue(string prefix)
		{
			if (_value == null)
				return "NULL";
			else
				return prefix + "  :  " + _value;
		}

		public string Value
		{
			set
			{
				_value = value;
			}
			get
			{
				if (_value == null)
					return "NULL";
				else
					return _value;
			}
		}
	}

class Program
{
	/// <summary>
	/// 主入口函数
	/// </summary>
	/// <param name="args"></param>
	static void Main(string[] args)
	{
		Type t = Type.GetType("csharplearnning.TestClass");
		Object[] constructParms = new object[] {"hello"};  
		TestClass obj = (TestClass)Activator.CreateInstance(t, constructParms);
		WriteLine(obj.GetType());
		ReadKey();
	}
}
	
8.3 获取方法以及动态调用方法
//获取类型信息
Type t = Type.GetType("csharplearnning.TestClass");
//构造器的参数
object[] constuctParms = new object[] { "timmy" };
//根据类型创建对象
object dObj = Activator.CreateInstance(t, constuctParms);
//获取方法的信息
MethodInfo method = t.GetMethod("GetValue");
//调用方法的一些标志位,这里的含义是Public并且是实例方法,这也是默认的值
BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
//GetValue方法的参数
object[] parameters = new object[] { "Hello" };
//调用方法,用一个object接收返回值
object returnValue = method.Invoke(dObj, flag, Type.DefaultBinder, parameters, null);
WriteLine(returnValue);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值