代码抽象层次
代码抽象层次
看了kent的实现模式,对代码抽象层次有了一点理解,kent首先问了一个问题,下面的代码有神马问题?
void compute()
{
int flag = input();
flag |= 1 ;
output(flag);
}
粗看来没有,但其实不然,但其实,input和output已经是高层抽象了,例如你并不知道输入来自于何方,到底是键盘输入呢,还是文件输入,又或者是网络输入,同样output也是如此,但是中间设置flag的语句则是一个低层抽象,如果整个函数都是低层抽象,代码应该是这样:
void compute()
{
int flag = 0 ;
scanf( " %d " ,& flag);
flag |= 1 ;
fprintf(golbalFileHandler, " %d\n " ,flag);
}
反之,如果函数是一个高层抽象的函数,代码应该是这样:
void compute()
{
int flag = input();
setFlag(flag);
output(flag);
}
更进一步的,如果flag的位1在业务逻辑的意义是数据以图表形式输出,那么代码应该是这样:
void compute()
{
int flag = input();
setOutputWithChart(flag);
output(flag);
}
将高层逻辑和低层逻辑剥离的最大好处时,高层逻辑不用管低层逻辑是怎么实现的,即所谓的解耦,低层逻辑从键盘读也好,从文件读也好,那是低层逻辑的事情,而且低层逻辑改变实现,这事对于高层逻辑也是透明的
疑问:
1)层次不应该太多,层次太多则小函数太多,未必好
2)不同层次的函数放在什么地方,这是个架构问题?
C#中IDisposable和IEnumerable、IEnumerator
C#中如何合理的释放非托管内存?在本文中我们将讲解使用IDisposable释放托管内存和非托管内存。
A. 首先需要让类实现IDisposable接口,然后实现IDispose方法。
A.a 核心Disponse(bool isDisponse)
1.此方法首先判断isReadyDisposed(判断是否第一次调用此核心方法),如果不是第一次调用则不做任何操作。
2.再判断是否是 析构函数调用?如果是析构函数调用不释放托管资源,其交由GC进行释放,如果析构函数释放托管资源可能之前GC释放过,就会导致出现异常。此判断内部释放托管资源内存。
3.释放非托管资源,并且设置标志位isReadyDisposed=true.
B. 然后分释放托管内存和非托管内存两种情况进行内存释放处理。
B.a 释放非托管内存
1.释放非托管内存需要手动调用本类的Dispose()方法,此方法首先调用Dispose(true)手动释放托管和非托管资源,然后调用GC.SuppressFinalize( this ),让GC不要再调用此对象的析构函数。
B.b 释放托管内存
1.释放托管内存是由GC自动调用析构函数,析构函数内部调用Dispose(false)方法.此时只释放非托管资源,而托管资源不管,由GC自行释放。
我们实现好的类代码如下:
public class IDisponseTest : IDisposable
{
private bool isReadyDisposed = false ;
~ IDisponseTest()
{
// 析构函数调用时不释放托管资源,因为交由GC进行释放
Disponse( false );
}
public void Dispose()
{
// 用户手动释放托管资源和非托管资源
Disponse( true );
// 用户已经释放了托管和非托管资源,所以不需要再调用析构函数
GC.SuppressFinalize( this );
// 如果子类继承此类时,需要按照如下写法进行。
// try
// {
// Disponse(true);
// }
// finally
// {
// base.Disponse();
// }
}
public virtual void Disponse( bool isDisponse)
{
// isReadyDisposed是控制只有第一次调用Disponse才有效才需要释放托管和非托管资源
if (isReadyDisposed)
return ;
if (isDisponse)
{
// 析构函数调用时不释放托管资源,因为交由GC进行释放
// 如果析构函数释放托管资源可能之前GC释放过,就会导致出现异常
// 托管资源释放
}
// 非托管资源释放
isReadyDisposed = true ;
}
}
C#制作一个迭代器对象?使用IEnumerable、IEnumerator
首先 :让类继承IEnumerable和IEnumerator接口,此时此类会出现IEnumerable.GetEnumerator()方法和IEnumerator.Current属性、IEnumerator.MoveNext(),IEnumerator.Reset()方法。
其次 :IEnumerator接口是对象遍历的方法和属性实现,而IEnumerable.GetEnumerator()方法是为了获取IEnumerator对象。
最后 :我们看看迭代器代码实现如下实例:
class Program
{
static void Main( string [] args)
{
CubeEnum cubelist = new CubeEnum( 50 );
foreach (Cube cube in cubelist)
{
Console.WriteLine( " 立方体长: " + cube.Length + " ,宽 " + cube.Width + " ,高 " + cube.Height);
}
Console.Read();
}
}
// 立方体,长、宽、高
public class Cube
{
public int Length { get ; set ; }
public int Width { get ; set ; }
public int Height { get ; set ; }
}
/// <summary>
/// 立方体迭代集合,继承了IEnumerable和IEnumerator
/// </summary>
public class CubeEnum : IEnumerable, IEnumerator
{
// 索引
public int Index { get ; set ; }
// 立方体集合
public Cube[] cubelist { get ; set ; }
// 初始化立方体集合
public CubeEnum( int count)
{
this .Index = - 1 ;
cubelist = new Cube[count];
for ( int i = 0 ; i < count; i++ )
{
cubelist[i] = new Cube();
cubelist[i].Length = i * 10 ;
cubelist[i].Width = i * 10 ;
cubelist[i].Height = i * 10 ;
}
}
// 实现IEnumerable的 GetEnumerator() 方法获得IEnumerator对象
public IEnumerator GetEnumerator()
{
return (IEnumerator) this ;
}
// 当前Cube立方体
public object Current
{
get { return cubelist[Index]; }
}
// 往下一步移动
public bool MoveNext()
{
Index ++ ;
if (Index < cubelist.Length)
{
return true ;
}
return false ;
}
// 重置索引
public void Reset()
{
Index = - 1 ;
}
}
本文讲述的是C#基础的应用,如有差错,敬请斧正。
分类: 代码风格&质量
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息