C# 泛型+扩展方法
8 评论209次阅读2010.10.15 17:17 作者:Felicia 编辑
C# 3.0及以后版本提供了扩展方法这一强大工具,使得动态扩展类变得十分方便。具体使用方法是定义一个static class,然后定义static扩展方法,注意扩展方法的第一个参数必须用this关键字修饰。扩展方法能像类本身定义的方法一样被使用,而不需要修改类的代码,这样扩展原有库中的类就变得非常容易了。扩展方法同样对接口生效,更牛X的是,扩展方法中同样可以使用泛型。
下面是一个例子,展示了怎样扩展IEnumerable接口,增加一个RandomSelect的方法用于在表中随机选取元素。
public static class IEnumerableExtensions
{
public static IEnumerable<T> RandomSelect<T>(this IEnumerable<T> input, int outputSize)
{
int size = input.Count();
if (outputSize < 0)
{
outputSize = 0;
}
if (outputSize > size)
{
outputSize = size;
}
List<int> index = new List<int>();
for (int i = 0; i < size; i++)
{
index.Add(i);
}
List<T> ret = new List<T>();
Random rand = new Random();
for (int i = 0; i < outputSize; i++)
{
int r = rand.Next() % (size - i);
ret.Add(input.ElementAt(index[r]));
index[r] = index[size - i - 1];
}
return ret;
}
}
使用方法和原生方法是一样一样的:)
List sourceList = new List() {1, 2, 3, 4, 5};
IEnumerable randomSelectedList = sourceList.RandomSelect(3);
在 C# 中实现 Singleton
发表评论2次阅读2009.12.23 12:51 作者:Felicia 编辑
我们需要只有一个实例的类,并且需要提供一个用于访问实例的全局访问点,还希望确保解决方案是线程安全的。
下面的实现仅允许一个线程在尚未创建 Singleton 实例的情况下进入关键区域(该区域由 lock 块标识)。
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
Error – Unable to find manifest signing certificate in the certificate store
发表评论55次阅读2009.12.10 18:02 作者:Felicia 编辑
I got this when I renamed my C# project then tried to publish it. To solve, I went to the “Signing” tab of the project properties and unchecked “Sign the ClickOnce manifests”.
Good luck!
C# Accurate Timer
发表评论46次阅读2009.10.12 10:59 作者:Felicia 编辑
C# 有三个标准定时器,分别是 System.Windows.Forms.Timer, System.Threading.Timer, System.Timers.Timer。
这三个Timer都不是很准确,无法进行精确到1毫秒的定时。经测试,这三种Timer的最小触发时间间隔是大约15毫秒。
因此我们必须寻找另外的方案。
Windows提供了用于多媒体的winmm.dll,可以满足高精度定时的要求。
下面是winmm.dll提供的API的C#包装。
{
//Lib API declarations
[DllImport("Winmm.dll", CharSet = CharSet.Auto)]
static extern uint timeSetEvent(uint uDelay, uint uResolution, TimerCallback lpTimeProc, UIntPtr dwUser, uint fuEvent);
[DllImport("Winmm.dll", CharSet = CharSet.Auto)]
static extern uint timeKillEvent(uint uTimerID);
[DllImport("Winmm.dll", CharSet = CharSet.Auto)]
static extern uint timeGetTime();
[DllImport("Winmm.dll", CharSet = CharSet.Auto)]
static extern uint timeBeginPeriod(uint uPeriod);
[DllImport("Winmm.dll", CharSet = CharSet.Auto)]
static extern uint timeEndPeriod(uint uPeriod);
//Timer type definitions
[Flags]
public enum fuEvent : uint
{
TIME_ONESHOT = 0, //Event occurs once, after uDelay milliseconds.
TIME_PERIODIC = 1,
TIME_CALLBACK_FUNCTION = 0x0000, /* callback is function */
//TIME_CALLBACK_EVENT_SET = 0x0010, /* callback is event - use SetEvent */
//TIME_CALLBACK_EVENT_PULSE = 0x0020 /* callback is event - use PulseEvent */
}
//Delegate definition for the API callback
delegate void TimerCallback(uint uTimerID, uint uMsg, UIntPtr dwUser, UIntPtr dw1, UIntPtr dw2);
//IDisposable code
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
Stop();
}
}
disposed = true;
}
~MMTimer()
{
Dispose(false);
}
/// <summary>
/// The current timer instance ID
/// </summary>
uint id = 0;
/// <summary>
/// The callback used by the the API
/// </summary>
TimerCallback thisCB;
/// <summary>
/// The timer elapsed event
/// </summary>
public event EventHandler Timer;
protected virtual void OnTimer(EventArgs e)
{
if (Timer != null)
Timer(this, e);
}
public MMTimer()
{
//Initialize the API callback
thisCB = CBFunc;
}
/// <summary>
/// Stop the current timer instance (if any)
/// </summary>
public void Stop()
{
lock (this)
{
if (id != 0)
{
timeKillEvent(id);
Console.WriteLine("MMTimer " + id.ToString() + " stopped");
id = 0;
}
}
}
/// <summary>
/// Start a timer instance
/// </summary>
/// <param name="ms">Timer interval in milliseconds</param>
/// <param name="repeat">If true sets a repetitive event, otherwise sets a one-shot</param>
public void Start(uint ms, bool repeat)
{
//Kill any existing timer
Stop();
//Set the timer type flags
fuEvent f = fuEvent.TIME_CALLBACK_FUNCTION | (repeat ? fuEvent.TIME_PERIODIC : fuEvent.TIME_ONESHOT);
lock (this)
{
id = timeSetEvent(ms, 0, thisCB, UIntPtr.Zero, (uint)f);
if (id == 0)
throw new Exception("timeSetEvent error");
Console.WriteLine("MMTimer " + id.ToString() + " started");
}
}
void CBFunc(uint uTimerID, uint uMsg, UIntPtr dwUser, UIntPtr dw1, UIntPtr dw2)
{
//Callback from the MMTimer API that fires the Timer event. Note we are in a different thread here
OnTimer(new EventArgs());
}
}
转到计科的第一学期结束了
发表评论8次阅读2008.07.01 21:28 作者:Felicia 编辑
今年做的最大的决定,就是转专业到计科了。我在转专业之前考虑了很久,最终确定我的确比较适合学习计算机,之后就毫不犹豫的转了。因为是大二下转专业,所以我要补修非常多的课。其实这个学期还好,也就比同班的人多上了大学语文,数字逻辑,c语言。不过由于这个学期比赛比较多,final回来之后又陆续参加了一些小的比赛,所以平时的课有的没有办法上了。期末的时候学习非常紧张,考试频繁,很多东西我又是第一次接触。比如我先学微机系统与接口技术,再学数字逻辑,再学汇编语言,完全是跟正常的专业培养方案反过来了。还好我发现自己对计算机专业的知识有较强的领悟能力,一切都还能掌握。期末考试之前我采用两天复习法,每天复习两小时,基本上搞定所有的课。就等出成绩啦,嘿嘿!
(全文 …)
