c#入门问题解决(三)

17.接口的多继承会带来哪些问题?

答:

C# 中的接口与类不同,可以使用多继承,即一个子接口可以有多个父接口。但如果两个父成员具有同名的成员,就产生了二义性(这也正是 C# 中类取消了多继承的原因之一),这时在实现时最好使用显式的声明

示例:
None.gif using  System; 
None.gif
using  System.Collections.Generic; 
None.gif
using  System.Text; 
None.gif  
None.gif
namespace  Example17 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
class Program 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
//一个完整的接口声明示例 
InBlock.gif
        interface IExample 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
//属性 
InBlock.gif
            string P 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
get
InBlock.gif                
set
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
//方法 
InBlock.gif
            string F(int Value); 
InBlock.gif            
//事件 
InBlock.gif
            event EventHandler E; 
InBlock.gif            
//索引指示器 
InBlock.gif
            string this[int Index] 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
get
InBlock.gif                
set
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }
 
InBlock.gif        
interface IA 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
int Count dot.gifgetset;} 
ExpandedSubBlockEnd.gif        }
 
InBlock.gif        
interface IB 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
int Count(); 
ExpandedSubBlockEnd.gif        }
 
InBlock.gif        
//IC接口从IA和IB多重继承 
InBlock.gif
        interface IC : IA, IB 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
ExpandedSubBlockEnd.gif        }
 
InBlock.gif        
class C : IC 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
private int count = 100
InBlock.gif            
//显式声明实现IA接口中的Count属性 
InBlock.gif
            int IA.Count 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif                
get dot.gifreturn 100; } 
ExpandedSubBlockStart.gifContractedSubBlock.gif                
set dot.gif{ count = value; } 
ExpandedSubBlockEnd.gif            }
 
InBlock.gif            
//显式声明实现IB接口中的Count方法 
InBlock.gif
            int IB.Count() 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                
return count * count; 
ExpandedSubBlockEnd.gif            }
 
ExpandedSubBlockEnd.gif        }
 
InBlock.gif        
static void Main(string[] args) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            C tmpObj 
= new C(); 
InBlock.gif  
InBlock.gif            
//调用时也要显式转换 
InBlock.gif
            Console.WriteLine("Count property: {0}", ((IA)tmpObj).Count); 
InBlock.gif            Console.WriteLine(
"Count function: {0}", ((IB)tmpObj).Count()); 
InBlock.gif  
InBlock.gif            Console.ReadLine(); 
ExpandedSubBlockEnd.gif        }
 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}
 
None.gif

结果:
Count property: 100
Count function: 10000 


18.抽象类和接口的区别?

答:

抽象类(abstract class)可以包含功能定义和实现,接口(interface)只能包含功能定义

抽象类是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性

分析对象,提炼内部共性形成抽象类,用以表示对象本质,即“是什么”

为外部提供调用或功能需要扩充时优先使用接口


19.别名指示符是什么?

答:

通过别名指示符我们可以为某个类型起一个别名

主要用于解决两个命名空间内有同名类型的冲突或避免使用冗余的命名空间

别名指示符只在一个单元文件内起作用

示例:
None.gif Class1.cs: 
None.gif
None.gif
using  System; 
None.gif
using  System.Collections.Generic; 
None.gif
using  System.Text; 
None.gif  
None.gif
namespace  com.nblogs.reonlyrun.CSharp26QExample.Example19.Lib01 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
class Class1 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
public override string ToString() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
return "com.nblogs.reonlyrun.CSharp26QExample.Example19.Lib01's Class1"
ExpandedSubBlockEnd.gif        }
 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}
 
None.gifClass2.cs 
None.gif
None.gif
using  System; 
None.gif
using  System.Collections.Generic; 
None.gif
using  System.Text; 
None.gif  
None.gif
namespace  com.nblogs.reonlyrun.CSharp26QExample.Example19.Lib02 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
class Class1 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
public override string ToString() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
return "com.nblogs.reonlyrun.CSharp26QExample.Example19.Lib02's Class1"
ExpandedSubBlockEnd.gif        }
 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}
 
None.gif主单元(Program.cs): 
None.gif
None.gif
using  System; 
None.gif
using  System.Collections.Generic; 
None.gif
using  System.Text; 
None.gif  
None.gif
// 使用别名指示符解决同名类型的冲突 
None.gif
using  Lib01Class1  =  com.nblogs.reonlyrun.CSharp26QExample.Example19.Lib01.Class1; 
None.gif
using  Lib02Class2  =  com.nblogs.reonlyrun.CSharp26QExample.Example19.Lib02.Class1; 
None.gif  
None.gif
namespace  Example19 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
class Program 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
static void Main(string[] args) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            Lib01Class1 tmpObj1 
= new Lib01Class1(); 
InBlock.gif            Lib02Class2 tmpObj2 
= new Lib02Class2(); 
InBlock.gif  
InBlock.gif            Console.WriteLine(tmpObj1); 
InBlock.gif            Console.WriteLine(tmpObj2); 
InBlock.gif  
InBlock.gif            Console.ReadLine(); 
ExpandedSubBlockEnd.gif        }
 
ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}
 
None.gif

结果:
com.nblogs.reonlyrun.CSharp26QExample.Example19.Lib01's Class1
com.nblogs.reonlyrun.CSharp26QExample.Example19.Lib02's Class1 

 

20.如何释放非托管资源?

答:

 .NET 平台在内存管理方面提供了GC(Garbage Collection),负责自动释放托管资源和内存回收的工作,但它无法对非托管资源进行释放,这时我们必须自己提供方法来释放对象内分配的非托管资源,比如你在对象的实现代码中使用了一个COM对象

最简单的办法,可以通过实现protected void Finalize()(析构函数会在编译时变成这个东东)来释放非托管资源,因为GC在释放对象时会检查该对象是否实现了 Finalize() 方法,如果是则调用它。但,据说这样会降低效率。。。

有一种更好的,那就是通过实现一个接口显式的提供给客户调用端手工释放对象的方法,而不是傻傻的等着GC来释放我们的对象(何况效率又那么低)

System 命名空间内有一个 IDisposable 接口,拿来做这事非常合适,就省得我们自己再声明一个接口了

另外补充一句,这种实现并不一定要使用了非托管资源后才用,如果你设计的类会在运行时有大些的实例(象 GIS 中的Geometry),为了优化程序性能,你也可以通过实现该接口让客户调用端在确认不需要这些对象时手工释放它们

示例:
None.gif using  System; 
None.gif
using  System.Collections.Generic; 
None.gif
using  System.Text; 
None.gif  
None.gif
namespace  Example20 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
class Program 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif
InBlock.gif        
class Class1 : IDisposable 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
InBlock.gif            
//析构函数,编译后变成 protected void Finalize(),GC会在回收对象前会调用调用该方法 
InBlock.gif
            ~Class1() 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
InBlock.gif                Dispose(
false); 
ExpandedSubBlockEnd.gif            }
 
InBlock.gif  
InBlock.gif            
//通过实现该接口,客户%8

21.P/Invoke是什么?

答:

在受控代码与非受控代码进行交互时会产生一个事务(transition) ,这通常发生在使用平台调用服务(Platform Invocation Services),即P/Invoke

如调用系统的 API 或与 COM 对象打交道,通过 System.Runtime.InteropServices 命名空间

虽然使用 Interop 非常方便,但据估计每次调用事务都要执行 10 到 40 条指令,算起来开销也不少,所以我们要尽量少调用事务

如果非用不可,建议本着一次调用执行多个动作,而不是多次调用每次只执行少量动作的原则

 

22.StringBuilder 和 String 的区别?

答:

String 虽然是一个引用类型,但在赋值操作时会产生一个新的对象,而 StringBuilder 则不会

所以在大量字符串拼接或频繁对某一字符串进行操作时最好使用 StringBuilder,不要使用 String

示例:

 

None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif 
None.gif
namespace  Example22
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
class Program
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
const int cycle = 100000;
InBlock.gif 
InBlock.gif            
long vTickCount = Environment.TickCount;
InBlock.gif            String str 
= null;
InBlock.gif            
for (int i = 0; i < cycle; i++)
InBlock.gif                str 
+= i.ToString();
InBlock.gif            Console.WriteLine(
"String: {0} MSEL", Environment.TickCount - vTickCount);
InBlock.gif 
InBlock.gif            vTickCount 
= Environment.TickCount;
InBlock.gif            
//看到这个变量名我就生气,奇怪为什么大家都使它呢? :)
InBlock.gif
            StringBuilder sb = new StringBuilder();
InBlock.gif            
for (int i = 0; i < cycle; i++)
InBlock.gif                sb.Append(i);
InBlock.gif            Console.WriteLine(
"StringBuilder: {0} MSEL", Environment.TickCount - vTickCount);
InBlock.gif 
InBlock.gif            Console.ReadLine();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif


结果:
String: 102047 MSEL
StringBuilder: 46 MSEL


23.explicit 和 implicit 的含义?

答:

explicit 和 implicit 属于转换运算符,如用这两者可以让我们自定义的类型支持相互交换

explicti 表示显式转换,如从 A -> B 必须进行强制类型转换(B = (B)A)

implicit 表示隐式转换,如从 B -> A 只需直接赋值(A = B)

隐式转换可以让我们的代码看上去更漂亮、更简洁易懂,所以最好多使用 implicit 运算符。不过!如果对象本身在转换时会损失一些信息(如精度),那么我们只能使用 explicit 运算符,以便在编译期就能警告客户调用端

示例:
 

None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif 
None.gif
namespace  Example23
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
class Program
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
//本例灵感来源于大话西游经典台词“神仙?妖怪?”--主要是我实在想不出什么好例子了
InBlock.gif
        class Immortal
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
public string name;
InBlock.gif            
public Immortal(string Name)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                name 
= Name;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
public static implicit operator Monster(Immortal value)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return new Monster(value.name + ":神仙变妖怪?偷偷下凡即可。。。");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
class Monster
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
public string name;
InBlock.gif            
public Monster(string Name)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                name 
= Name;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
public static explicit operator Immortal(Monster value)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return new Immortal(value.name + ":妖怪想当神仙?再去修炼五百年!");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Immortal tmpImmortal 
= new Immortal("紫霞仙子");
InBlock.gif            
//隐式转换
InBlock.gif
            Monster tmpObj1 = tmpImmortal;
InBlock.gif            Console.WriteLine(tmpObj1.name);
InBlock.gif 
InBlock.gif            Monster tmpMonster 
= new Monster("孙悟空");
InBlock.gif            
//显式转换
InBlock.gif
            Immortal tmpObj2 = (Immortal)tmpMonster;
InBlock.gif            Console.WriteLine(tmpObj2.name);
InBlock.gif 
InBlock.gif            Console.ReadLine();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

 

结果:
紫霞仙子:神仙变妖怪?偷偷下凡即可。。。
孙悟空:妖怪想当神仙?再去修炼五百年!

 
24.params 有什么用?

答:

params 关键字在方法成员的参数列表中使用,为该方法提供了参数个数可变的能力

它在只能出现一次并且不能在其后再有参数定义,之前可以

示例:

 

None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif 
None.gif
namespace  ConsoleApplication1
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
class App
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
//第一个参数必须是整型,但后面的参数个数是可变的。
InBlock.gif        
//而且由于定的是object数组,所有的数据类型都可以做为参数传入
InBlock.gif
        public static void UseParams(int id, params object[] list)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(id);
InBlock.gif            
for (int i = 0; i < list.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(list[i]);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif 
InBlock.gif        
static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//可变参数部分传入了三个参数,都是字符串类型
InBlock.gif
            UseParams(1"a""b""c");
InBlock.gif            
//可变参数部分传入了四个参数,分别为字符串、整数、浮点数和双精度浮点数数组
ExpandedSubBlockStart.gifContractedSubBlock.gif
            UseParams(2"d"10033.33new double[] dot.gif1.12.2 });
InBlock.gif 
InBlock.gif            Console.ReadLine();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif


结果:
1
a
b
c
2
d
100
33.33
System.Double[]


25.什么是反射?

答:

反射,Reflection,通过它我们可以在运行时获得各种信息,如程序集、模块、类型、字段、属性、方法和事件

通过对类型动态实例化后,还可以对其执行操作

一般用于插件式框架程序和设计模式的实现,当然反射是一种手段可以充分发挥其能量来完成你想做的任何事情(前面好象见过一位高人用反射调用一个官方类库中未说明的函数。。。)

示例:

 

None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif 
None.gif
namespace  Example25Lib
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public class Class1
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private string name;
InBlock.gif        
private int age;
InBlock.gif 
InBlock.gif        
//如果显式的声明了无参数构造函数,客户端只需要用程序集的CreateInstance即可实例化该类
InBlock.gif        
//在此特意不实现,以便在客户调用端体现构造函数的反射实现
InBlock.gif        
//public Class1()
InBlock.gif        
//{
InBlock.gif        
//}
InBlock.gif
        public Class1(string Name, int Age)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            name 
= Name;
InBlock.gif            age 
= Age;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public void ChangeName(string NewName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            name 
= NewName;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public void ChangeAge(int NewAge)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            age 
= NewAge;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public override string ToString()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return string.Format("Name: {0}, Age: {1}", name, age);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif反射实例化对象并调用其方法,属性和事件的反射调用略去
None.gif
None.gif
using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif 
None.gif
// 注意添加该反射的命名空间
None.gif
using  System.Reflection;
None.gif 
None.gif
namespace  Example25
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
class Program
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//加载程序集
InBlock.gif
            Assembly tmpAss = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "Example25Lib.dll");
InBlock.gif 
InBlock.gif            
//遍历程序集内所有的类型,并实例化
InBlock.gif
            Type[] tmpTypes = tmpAss.GetTypes();
InBlock.gif            
foreach (Type tmpType in tmpTypes)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
//获取第一个类型的构造函数信息
InBlock.gif
                ConstructorInfo[] tmpConsInfos = tmpType.GetConstructors();
InBlock.gif                
foreach (ConstructorInfo tmpConsInfo in tmpConsInfos)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
//为构造函数生成调用的参数集合
InBlock.gif
                    ParameterInfo[] tmpParamInfos = tmpConsInfo.GetParameters(); 
InBlock.gif                    
object[] tmpParams = new object[tmpParamInfos.Length];
InBlock.gif                    
for (int i = 0; i < tmpParamInfos.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        tmpParams[i] 
= tmpAss.CreateInstance(tmpParamInfos[i].ParameterType.FullName);
InBlock.gif                        
if (tmpParamInfos[i].ParameterType.FullName == "System.String")
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            tmpParams[i] 
= "Clark";
ExpandedSubBlockEnd.gif                        }

ExpandedSubBlockEnd.gif                    }

InBlock.gif 
InBlock.gif                    
//实例化对象
InBlock.gif
                    object tmpObj = tmpConsInfo.Invoke(tmpParams);
InBlock.gif                    Console.WriteLine(tmpObj);
InBlock.gif 
InBlock.gif                    
//获取所有方法并执行
InBlock.gif
                    foreach (MethodInfo tmpMethod in tmpType.GetMethods())
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
//为方法的调用创建参数集合
InBlock.gif
                        tmpParamInfos = tmpMethod.GetParameters();
InBlock.gif                        tmpParams 
= new object[tmpParamInfos.Length];
InBlock.gif                        
for (int i = 0; i < tmpParamInfos.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            tmpParams[i] 
= tmpAss.CreateInstance(tmpParamInfos[i].ParameterType.FullName);
InBlock.gif                            
if (tmpParamInfos[i].ParameterType.FullName == "System.String")
ExpandedSubBlockStart.gifContractedSubBlock.gif                            
dot.gif{
InBlock.gif                                tmpParams[i] 
= "Clark Zheng";
ExpandedSubBlockEnd.gif                            }

InBlock.gif                            
if (tmpParamInfos[i].ParameterType.FullName == "System.Int32")
ExpandedSubBlockStart.gifContractedSubBlock.gif                            
dot.gif{
InBlock.gif                                tmpParams[i] 
= 27;
ExpandedSubBlockEnd.gif                            }

ExpandedSubBlockEnd.gif                        }

InBlock.gif                        tmpMethod.Invoke(tmpObj, tmpParams);
ExpandedSubBlockEnd.gif                    }

InBlock.gif 
InBlock.gif                    
//调用完方法后再次打印对象,比较结果
InBlock.gif
                    Console.WriteLine(tmpObj);
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif 
InBlock.gif            Console.ReadLine();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif


结果:
Name: Clark, Age: 0
Name: Clark Zheng, Age: 27

转载于:https://www.cnblogs.com/lynnwayne/archive/2007/06/08/777135.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值