C# - etc
const 배열을 정의 할 수 없을 때
static readonly int[] LEVEL_TABLE = { 1, 2, 3, 4, 5 };
static readonly string[] STR_TABLE = { "NONE", "1", "2", "3" };
다른 클래스에 있는 const로 정의한 상수를 이용 방법
상수는 다음과 같이 정의 되어 있다.
public class PacketDefine
{
Public const int Packet_First = 0;
………..
}
이것을 Command 클래스에서 사용 할려면
Int packetfirst = PacketDefine.Packet_First;
로 사용한다.
데이터 변환
데이터 변환을 위해서는 Convert의 멤버를 사용한다.
Convert.Toxxx( xxx )를 사용하면 된다. 예) 스트링을 int 변환
Convert.ToInt32( string );
문자열이 숫자인지 검사
int_TryParse를 사용한다.
int i = 0;
string s = "108";
bool result = int.TryParse(s, out i); //i now = 108
바이트 배열을 지정된 위치와 크기로 복사할 경우
Buffer.BlockCopy( ……. );
클래스의 크기를 알고 싶을 때
Marshal.SizeOf(LoginPacket)
LoginPacket는 인스턴스 화된 객체이어야만 한다. LoginPacket의 클래스인 LOGIN_PACKET를 사용하면 안된다.
메시지 박스
일반 메시지 박스 사용
MessageBox.Show( "클라이언트에서 사용할 스킬 정보를 파일로 저장 하겠습니까 ?" );
// YES / NO 버튼 사용
if( DialogResult.Yes == MessageBox.Show( "클라이언트에서 사용할 스킬 정보를 파일로 저장 하겠습니까 ?", "이진 파일 저장", MessageBoxButtons.YesNo ) )
한글 파일 출력 문제
정확한 이유는 모르지만 한글을 파일에 입력할 때 인코딩을 Default 방식으로 지정하면 한글 XP에서는 한글을 아스키 코드 값으로 제대로 인식하지만 윈도우 2003에서는 한글을 유니코드 방식으로 인식하여 한글 1글자를 아스키 코드 1글자로 인식하는 경우가 있다.
string strValue = “개”;
encodedBytes = System.Text.Encoding.Default.GetBytes(strValue);
한글 XP에서 읽는다면 encodedBytes의 길이가 2개로 나오지만 윈도우 2003에서는 길이가 1로 된다.
이 문제를 해결할려면 인코딩 방식을 명시적으로 지정해야 된다.
string strValue = “개”;
encodedBytes = System.Text.Encoding.GetEncoding(949).GetBytes(strValue);
한글이 포함된 Ansi 문자열을 유니코드 문자열로 변환하기
byte[] data;
string s = System.Text.Encoding.GetEncoding(949).GetString(data);
폼의 마우스 커서 변경
화살표 마우스 커서 this.Cursor = Cursors.Arrow;
모래시계 커서 this.Cursor = Cursors. WaitCursor;
손 커서 this.Cursor = Cursors. Hand;
기본 커서 this.Cursor = Cursors. Default;
등등…….
네이티브의 time(&time_t)에서 얻은 초단위의 시간을 C#에서 사용
time함수를 이용하여 얻은 시간은 시작이 1970년부터이고 C#의 경우는 0년 1월1일 부터이다..그래서 서로 호환이 되지 않느다. 이것을 해결할려면 다음과 같이 하면 된다.
int iTime = C타임함수값;
DateTime dt = new DateTime(1970, 1, 1, 9, 0, 0); // 한국은 GMT+9시간
dt = dt.AddSeconds(iTime);
로그 메시지 출력을 위한 가변인수와 매크로
C++에서는 로그를 남기기 위해 로그 라이브러리를 만들 때 꼭 사용하는 것이 가변인수와 매크로입니다.
가변인수를 사용하여
void LogMessage( LPCTSTR format, ... )
{
char SBody[ MAX_PATH ] = { 0, };
va_list strlist;
va_start( strlist, format );
_vsntprintf_s( SBody, _countof(SBody), _TRUNCATE, format, strlist );
va_end( strlist );
}
이런 식으로 하나의 메시지를 만들고
이 LogMessage함수를 어디서, 언제 호출했는지 알리는 방법은 FILE, LINE, FUNCTION 와 같은 매크로를 사용합니다.
이런 기능을 닷넷에서 구현하려면 가변인수는 다음과 같은 방식으로 구현 합니다.
public void print(int i, params string[] messages)
{
string logmsg;
foreach(string msg in messages)
logmsg += msg;
}
그리고 FILE, LINE, FUNCTION 매크로는 닷넷의 어트리뷰트를 사용합니다.
using System.Runtime.CompilerServices;
using System.Diagnostics;
void LogToUI(string logText,
[CallerFilePath] string fileName = "",
[CallerMemberName] string methodName = "",
[CallerLineNumber] int lineNumber = 0)
{
string logmsg = string.Format("[줄:{0}|호출:{1}|시간{2}] : {3}", lineNumber, methodName, DateTime.Now.ToShortTimeString(), logText);
listBoxLog.Items.Add(logmsg);
}
// 사용
LogToUI("서버 생성 성공");
VS 출력창에 로그 출력
디버깅 시 Visual Studio의 출력 창에 로그를 남기고 싶을 때는 다음과 같이 한다.
System.Diagnostics.Debug.WriteLine(contents.ToString());
public static bool ResetThreadPool(int? maxWorkingThreads, int? maxCompletionPortThreads)
public static bool ResetThreadPool(int? maxWorkingThreads, int? maxCompletionPortThreads, int? minWorkingThreads, int? minCompletionPortThreads)
{
if (maxWorkingThreads.HasValue || maxCompletionPortThreads.HasValue)
{
}
}
AppDomain
- 응용 프로그램에서 AppDomain 과연 어디다 쓸까? (AppDomain을 이용한 어셈블리 로딩) - 1 http://blog.naver.com/vactorman/80166702004
- 응용 프로그램에서 AppDomain 과연 어디다 쓸까? (AppDomain을 이용한 어셈블리 로딩) - 2 http://blog.naver.com/vactorman/80166705025
- AppDomain 사용 예 http://blog.naver.com/psy10604/70127422123
app.config 파일을 사용하여 프로그램 설정 읽기 및 저장
- http://samurae83.blog.me/90174661488
static void PrintSettingInfo()
{
Console.WriteLine("[ServerAddress]: {0}", ConsoleApp.Properties.Settings.Default.ServerAddress);
Console.WriteLine("[AccountDB]: {0}", ConsoleApp.Properties.Settings.Default.AccountDB);
var gameDBList = ConsoleApp.Properties.Settings.Default.GameDB;
foreach (var address in gameDBList)
{
Console.WriteLine("[GameDB]: {0}", address);
}
var redisList = ConsoleApp.Properties.Settings.Default.Redis;
foreach (var address in redisList)
{
Console.WriteLine("[Redis]: {0}", address);
}
}
콘솔 스타일의 외부 프로세스를 실행한 후 결과얻기(혹은 윈도우의 태스크스케줄러 정보를 Linq로 분석)
- 출처: [http://d.hatena.ne.jp/kkamegawa/20101222/p1]
- C:>schtasks /query /XML ONE 로 태스크 스케줄러의 내용을 xml으로 출력할 수 있다.
using System;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
namespace AvendCalender
{
public class TaskInfo
{
var schTasks = new Process();
schTasks.StartInfo.Arguments = "/query /XML ONE ";
schTasks.StartInfo.FileName = "schtasks.exe";
schTasks.StartInfo.UseShellExecute = false;
schTasks.StartInfo.RedirectStandardOutput = true;
schTasks.Start();
string xmlText = schTasks.StandardOutput.ReadToEnd();
XDocument xtaskXml = XDocument.Parse(xmlText);
schTasks.WaitForExit();
schTasks.Close();
XNamespace xnSchTasks = "http://schemas.microsoft.com/windows/2004/02/mit/task";
var xmlTasks = from x in xTasksList.Root.Elements(xnSchTasks + "Task")
select x;
}
}
멀티코어 JIT 유효화 하기
- 닷넷 4.5에서 추가된 기능
- 말 그대로 멀티 코어 환경에서 병렬로 JIT을 하는 기능.
- 이것에 의해 애플리케이션의 동작에 선행하여 필요한 메소드를 JIT 할 가능성이 높아져서 결과적으로 애플리케이션 성능이 올라간다.
- ASP.NET과 실버라이트에서는 기본으로 유효화 되어 있지만 데스크탑 애플리케이션에서는 기본은 사용하지 않게 되어 있다. ** 이유는 이 기능을 사용하기 위해서는 프로파일링 처리가 필요하여 프로파일링 데이터를 보존해야 하기 때문이다. 데스크탑 애플리케이션에서는 어디에 데이터를 보존해야 할지 모르기 때문에 수동으로 해야 한다.
- 사용
ProfileOptimization.SetProfileRoot(Environment.CurrentDirectory);
ProfileOptimization.StartProfile("App.JIT.Profile");
- 참고
- [http://d.hatena.ne.jp/gsf_zero1/20121025/p1]
- [http://blogs.msdn.com/b/dotnet/archive/2012/10/18/an-easy-solution-for-improving-app-launch-performance.aspx]
- [http://stackoverflow.com/questions/12965606/why-is-multicore-jit-not-on-by-default-in-net-4-5]
- [http://msdn.microsoft.com/ja-jp/magazine/hh882452.aspx]
System.Threading.Timer의 중복 콜백 호출
- System.Threading.Timer의 콜백 메소드 내에서 시간이 걸리는 처리가 있으며 콜백 매소드 처리 중에 또 다른 콜백이 호출된다.
- 예를 들면 콜백 호출 폭이 500밀리초인 경우 처리가 700밀리초 걸리는 경우 중복으로 콜백이 호출된다.
- 참고
- [http://d.hatena.ne.jp/gsf_zero1/20120507/p1]
보안 문자 생성하기
public static int GenerateSecureNumber()
{
var SecureNumberRandom = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
var number = SecureNumberRandom.Next(15271493, 598410861);
return number;
}
public static string GenerateSecureNumber2(int startNumber, int endNumber, int count)
{
var SecureNumberRandom = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
StringBuilder secureString = new StringBuilder();
for( int i = 0; i < count; ++i )
{
secureString.Append(SecureNumberRandom.Next(startNumber, endNumber).ToString());
}
return secureString.ToString();
}
// 출처: http://stackoverflow.com/questions/54991/generating-random-passwords
public static string GenerateSecureString(int lowercase, int uppercase, int numerics)
{
string lowers = "abcdefghijklmnopqrstuvwxyz";
string uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string number = "0123456789";
Random random = new Random();
string generated = "!";
for (int i = 1; i <= lowercase; i++)
generated = generated.Insert(
random.Next(generated.Length),
lowers[random.Next(lowers.Length - 1)].ToString()
);
for (int i = 1; i <= uppercase; i++)
generated = generated.Insert(
random.Next(generated.Length),
uppers[random.Next(uppers.Length - 1)].ToString()
);
for (int i = 1; i <= numerics; i++)
generated = generated.Insert(
random.Next(generated.Length),
number[random.Next(number.Length - 1)].ToString()
);
return generated.Replace("!", string.Empty);
}
public static string GenerateSecureString2()
{
Guid g = Guid.NewGuid();
string guidString = Convert.ToBase64String(g.ToByteArray());
guidString = guidString.Replace("=", "");
guidString = guidString.Replace("+", "");
return guidString;
}
특정 경고 무시
- 하나의 파일에서만 적용된다.
- #pragma warning disable warning-list
- #pragma warning restore warning-list
#pragma warning disable 414, 3021
[CLSCompliant(false)]
public class C
{
int i = 1;
static void Main()
{
}
}
값 타입에 null 대입
int, double과 같은 값 타입은 null을 대입할 수 없지만 변수 선언 시 ?을 같이 사용하면 null 대입이 가능하다.
static class 갑타입Null
{
public static void Check()
{
int? y = null;
if (y == null)
{
Console.WriteLine("y는 null");
y = 11;
Console.WriteLine("y는 {0}", y);
}
int? yy = GetIntValue();
if (yy == null)
{
Console.WriteLine("yy는 null");
}
}
static int? GetIntValue()
{
return null;
}
}
변수 대입 시에 null 조사와 대입을 한 번에 하기
static class Null_조사와_대입을_한번에
{
public static void Check1()
{
int x1 = 10;
int x2 = x1 > 10 ? 0 : x1;
Console.WriteLine("x2는 {0}", x2);
x1 = 11;
int x3 = x1 >= 10 ? 0 : x1;
Console.WriteLine("x3는 {0}", x3);
}
public static void Check2()
{
TEST test1 = null;
var test2 = test1 ?? new TEST() { x = 10 };
Console.WriteLine("test2.x: {0}", test2.x);
}
class TEST
{
public int x;
}
}
익명 타입
static class 익명형
{
public static void Test()
{
var character = new { ID = 11, Name = "test" };
Console.WriteLine("캐릭터 ID:{0}, Name:{1}", character.ID, character.Name);
}
}
const로 배열이나 오브젝트를 선언하고 싶을 때는 static readonly 사용
const int MaxValue = 100;
const Vector2 Pos = new Vector2(100, 100); // error
static readonly Vector2 Pos = new Vector2(100, 100);
읽기 전용 컬렉션 만들기
static class 읽기전용컬렉션
{
static List<int> IntList = new List<int>();
public static void Test()
{
IntList.Add(11);
IntList.Add(12);
var list = GetList();
foreach(var value in list)
{
Console.WriteLine(value);
}
}
static System.Collections.ObjectModel.ReadOnlyCollection<int> GetList()
{
return IntList.AsReadOnly();
}
}
메소드 체인
- 메소드가 자신 자신의 인스턴스를 반환하는 패턴이라면 메소드 체인이 성립한다
Sample hoge = new Sample();
hoge.Piyo.Value = 100;
list.Add( hoge ); // vode를 반환
위 코드의 Add 메소드를 메소드 체인 지원으로 바꾸면 간략하게 기술 할 수 있다.
- 확장 메소드
public static T Chain<T>( this T source , Action<T> call ) {
if( source == null )
return source;
call( source );
return source;
}
사용 예
new Sample()
.Chain( x => x.Piyo.Value = 100 )
.Chain( x => list.Add( x ) );
- 출처: http://qiita.com/Temarin_PITA/items/001f71d70474063caab5
이 글은 2019-04-10에 작성되었습니다.