레이블이 C#인 게시물을 표시합니다. 모든 게시물 표시
레이블이 C#인 게시물을 표시합니다. 모든 게시물 표시

2016년 9월 6일 화요일

Simple C# Database access framework



namespace NIHDatabase.RDS
{
    internal class NIHDbContext : DbContext
    {
        internal NIHDbContext(string connStr) : base(connStr) { }
    }
    public class NIHRdsService
    {
        public string _connStr { get; set; }
        public NIHRdsService() { }

        #region Multi Result
        /// <summary>
        /// Multi Result
        /// </summary>
        /// <param name="procedureName"></param>
        /// <param name="parameters"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public DataSet SqlMultiResult(string procedureName, object parameters, Func<object, string, ProcedureAndParameterModel> func)
        {
            DataSet ds = new DataSet();
            using (SqlConnection conn = new SqlConnection(_connStr))
            {
                SqlDataAdapter adapter = new SqlDataAdapter();
                adapter.SelectCommand  = new SqlCommand(procedureName, conn);
                adapter.SelectCommand.Parameters.AddRange(func(parameters, procedureName).Parameters);
                adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
                adapter.Fill(ds);
            }

            return ds;
        }
        #endregion

        #region SqlQuery<T>
        /// <summary>
        /// 특정 조건에 맞는 단일 데이터 조회
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="procedureName"></param>
        /// <param name="parameters"></param>
        /// <param name="func"></param>
        /// <returns>T</returns>
        public async Task<T> SqlQuerySingle<T>(string procedureName, object parameters, Func<object, string, ProcedureAndParameterModel> func)
        {
            using (var context = new NIHDbContext(_connStr))
            {
                ProcedureAndParameterModel _model = func(parameters, procedureName);
                return await context.Database.SqlQuery<T>(_model.ProcedureName, _model.Parameters).SingleAsync();
            }
        }
        /// <summary>
        /// 파라미터 없이 전체 테이블 스캔
        /// </summary>
        /// <typeparam name="T">object</typeparam>
        /// <param name="procedureName">string</param>
        /// <returns>List<T></returns>
        public async Task<List<T>> SqlQueryMulti<T>(string procedureName)
        {
            using (var context = new NIHDbContext(_connStr))
            {
                return await context.Database.SqlQuery<T>(procedureName).ToListAsync();
            }
        }
        /// <summary>
        /// 특정 조건을 맞족하는 데이터 레코드 조회
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="procedureName"></param>
        /// <param name="parameters"></param>
        /// <param name="func"></param>
        /// <returns>List<T></returns>
        public async Task<List<T>> SqlQueryMulti<T>(string procedureName, object parameters, Func<object, string, ProcedureAndParameterModel> func)
        {
            using (var context = new NIHDbContext(_connStr))
            {
                ProcedureAndParameterModel _model = func(parameters, procedureName);
                return await context.Database.SqlQuery<T>(_model.ProcedureName, _model.Parameters).ToListAsync();
            }
        }
        #endregion

        #region ExecuteSqlCommandAsync
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="procedureName"></param>
        /// <param name="parameters"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public async Task<int> ExecuteCommandAsync<T>(string procedureName, object parameters, Func<object, string, ProcedureAndParameterModel> func)
        {
            using (var context = new NIHDbContext(_connStr))
            {
                ProcedureAndParameterModel _model = func(parameters, procedureName);
                return await context.Database.ExecuteSqlCommandAsync(_model.ProcedureName, _model.Parameters);
            }
        }
        #endregion
    }
}

SqlQuery 문 생성, DataTable에서 List로 변환

namespace NIHDatabase.RDS
{
    public static class DataHelper
    {
        /// <summary>
        /// 프로시저명과, 파라미터 모델을 받아서
        /// ProcedureAndParameter타입으로 반환
        /// </summary>
        /// <typeparam name="T">Parameter Entity</typeparam>
        /// <param name="model"></param>
        /// <param name="procName"></param>
        /// <returns></returns>
        public static ProcedureAndParameterModel GetSqlQueryString<T>(this T model, string ProcedureName)
        {
            List<SqlParameter> _parameters = new List<SqlParameter>();
            StringBuilder      _quryString = new StringBuilder(ProcedureName);

            if(model!=null)
            {
                bool _first = true;
                foreach (var prop in typeof(T).GetProperties())
                {
                    // 파라미터 명
                    var _name  = prop.Name;
                    // 파라미터 값
                    var _value = prop.GetValue(model, null);
                    // SqlParameter 값이 NULL이면 DBNull.Value로 설정
                    var _param = new SqlParameter($"@{_name}", _value == null ? DBNull.Value : _value);
                    // 파라미터 배열에 추가
                    _parameters.Add(_param);

                    // Sql Query문 설정
                    if (_first)
                    {
                        _quryString.Append($" @{_name}");
                        _first = false;
                    }
                    else
                    {
                        _quryString.Append($", @{_name}");
                    }
                }
            }
            
            return new ProcedureAndParameterModel { ProcedureName = _quryString.ToString(), Parameters = _parameters.ToArray() };
        }

        /// <summary>
        /// DataTable => List<T>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <returns>List<T></returns>
        public static List<T> ToList<T>(this DataTable table) where T : new()
        {
            IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
            List<T> result = new List<T>();

            foreach (var row in table.Rows)
            {
                var item = CreateItemFromRow<T>((DataRow)row, properties);
                result.Add(item);
            }

            return result;
        }

        private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
        {
            T item = new T();

            foreach (var prop in properties)
            {
                prop.SetValue(item, row[prop.Name], null);
            }
            return item;
        }
    }
}

2016년 4월 30일 토요일

[C#] Callback Func



예제 1

namespace Cshop_v6._0
{
    delegate int GetResultDelegate();

    class Target
    {
        public void Do(GetResultDelegate getResult)
        {
            Console.WriteLine(getResult()); // 콜백 메서드 호출
        }
    }

    class Source
    {
        public int GetResult() // 콜백 용도로 전달된 메서드
        {
            return 10;
        }

        public void Test()
        {
            Target target = new Target();
            target.Do(new GetResultDelegate(this.GetResult));
        }
    }
}

예제 2

namespace Cshop_v6._0
{
    delegate int GetResultDelegate(int x, int y);

    class Target
    {
        public void Do(GetResultDelegate getResult, int x, int y)
        {
            Console.WriteLine(getResult(x, y));
        }
    }

    class Source
    {
        public static int GetResult(int x, int y)
        {
            return x * y;
        }

        public static void Main()
        {
            Target target = new Target();
            GetResultDelegate gd = GetResult;
            target.Do(gd, 5, 10);
        }
    }
}

[C#] Delegate



접근제한자 delegate 대상_메서드_반환타입 식별자(… … 대상_메서드_매개변수_목록 … …);

예제 1

namespace Cshop_v6._0
{
    public class Mathematics
    {
        delegate int CalcDelegate(int x, int y);

        static int Add(int x, int y)      { return x + y; }
        static int Subtract(int x, int y) { return x - y; }
        static int Multiply(int x, int y) { return x * y; }
        static int Devide(int x, int y)   { return x / y; }

        CalcDelegate[] methods;

        public Mathematics()
        {
            methods = new CalcDelegate[] { Mathematics.Add, Mathematics.Subtract, Mathematics.Multiply, Mathematics.Devide };
        }

        public void Calculate(char opCode, int operand1, int operand2)
        {
            switch (opCode)
            {
                case '+': Console.WriteLine("+: " + methods[0](operand1, operand2)); break;
                case '-': Console.WriteLine("-: " + methods[1](operand1, operand2)); break;
                case '*': Console.WriteLine("*: " + methods[2](operand1, operand2)); break;
                case '/': Console.WriteLine("/: " + methods[3](operand1, operand2)); break;
            }
        }
    }

    class Program
    {
        delegate void WorkDelegate(char arg1, int arg2, int arg3);

        static void Main()
        {
            Mathematics math = new Mathematics();
            WorkDelegate work = math.Calculate;

            work('+', 10, 5);
            work('-', 10, 5);
            work('*', 10, 5);
            work('/', 10, 5);
        }
    }
}

예제 2

namespace Cshop_v6._0
{
    class Program
    {
        delegate void CalcDelegate(int x, int y);

        static void Add(int x, int y) { Console.WriteLine(x + y); }
        static void Subtract(int x, int y) { Console.WriteLine(x - y); }
        static void Multiply(int x, int y) { Console.WriteLine(x * y); }
        static void Divide(int x, int y) { Console.WriteLine(x / y); }

        static void Main()
        {
            CalcDelegate calc = Add;
            calc += Subtract;
            calc += Multiply;
            calc += Divide;

            calc(10, 5);

            // 출력결과
            /*
            15
            5
            50
            2
            */

            Console.WriteLine("=================================================================");

            calc -= Divide;

            calc(10, 5);


            // 출력결과
            /*
            15
            5
            50
            */
        }
    }
}

2016년 4월 22일 금요일

[C#] Lambda expression-1



코드로서의 람다식

class Program
{
    delegate int? MyDivide(int a, int b);
    static void Main(string[] args)
    {
        MyDivide myFunc = (a, b) =>
        {
            if (b == 0)
            {
                return null;
            }
            return a / b;
        };
        Console.WriteLine("10 / 0 = " + myFunc(10, 0));
     }
}

Func, Action 델리게이트를 이용한 Lambda expression

// public delegate void Action(T obj);
// 반환값이 없는 델리게이트로서 T 형식 매개변수는 입력될 인자 1개의 타입을 지정

// public delegate TResult Func();
// 반환값이 있는 델리게이트로서 TResult 형식 매개변수는 반환될 타입을 지정

class Program
{
    static void Main()
    {
        Action log = (text) =>
        {
            Console.WriteLine(text);
        };

        log("Hello world!");

        Func age = (a, b) => a + b;

        Console.WriteLine(age(14, 14));
    }
}

/*
public delegate void Action(T arg);
public delegate void Action(T1 arg1, T2 arg2);
...
T1~T16까지 Action delegate 정의

public delegate TResult Func();
public delegate TResult Func(T arg);
public delegate TResult Func(T1 arg1, T2 arg2);
...
T1 ~ T16까지 Func delegate 정의
*/

Collection & Lambda expression [ForEach]

// List에 정의된 ForEach
// public void ForEach(Action action);

// Array에 정의된 ForEach
// public static void ForEach(T [] array, Action action);
class Program
{
    static void Main()
    {
        List list = new List { 1, 2, 3, 10, 100 };

        // 일반형식
        foreach(var item in list)
        {
            Console.WriteLine(item + " * 2 == " + (item * 2));
        }

        // 람다식
        list.ForEach((elem) => { Console.WriteLine(elem + " * 2 == " + (elem * 2)); });
        // 또는
        Array.ForEach(list.ToArray(), (elem) => { Console.WriteLine(elem + " * 2 == " + (elem * 2)); });
    }
}

Collection & Lambda expression [FindAll, Where, Count, Select]

class Program
{
    static void Main()
    {

        List list = new List { 1, 2, 3, 10, 100, 501 };

        // 짝수로 구성된 리스트 반환
        List result = new List();

        // 일반형식
        foreach (var item in list)
        {
            if (item % 2 == 0)
            {
                result.Add(item);
            }
        }
        
        // FindAll
        result = list.FindAll((elem) => elem % 2 == 0);
 
        // Where
        IEnumerable enumList = list.Where((elem) => elem % 2 == 0);

        // Count
        int count = list.Count((elem) => elem > 3);

        // Select
        IEnumerable doubleList = list.Select((elem) => (double)elem);
        IEnumerable personList = list.Select((elem) => new Person {Age = elem, Name = Guid.NewGuid().ToString()});
        var itemList = list.Select((elem) => new {TypeNo = elem, CreateDate = DateTime.Now});
    }
}
class Person
{
    public int Age {get; set;}
    public string Name {get; set;}
}

2016년 4월 16일 토요일

호출자 정보 [CallerMemberName], [CallerFilePath], [CallerLineNumber]




CallerMemberName : 호출자 정보가 명시된 메서드를 호출한 측의 메서드 이름
CallerFilePath           : 호출자 정보가 명시된 메서드를 호출한 측의 소스코드 파일 경로
CallerLineNumber    : 호출자 정보가 명시된 메서드를 호출한 측의 소스코드 라인 번호


using System;
using System.Runtime.CompilerServices;

namespace ConsoleApplication1 
{
    class Program 
    {
        static void Main(string[] args) 
        {
            LogMessage("test log");
        }

        static void LogMessage(string text, [CallerMemberName] string memberName = "", 
                                            [CallerFilePath]   string filePath = "", 
                                            [CallerLineNumber] string lineNumber = "") 
        {
            Console.WriteLine("Text : " + text);
            Console.WriteLine("LogMessage CallerName : " + memberName);…
            Console.Writeline("LogMessage CallerLineNumber : " + lineNumber);
        }
    }
}

2015년 9월 13일 일요일

EF 6 Stored Procedure



단일값 반환
var param = new SqlParameter { ParameterName = "idx", Value = 1 };
var result = context.Database.SqlQuery("ProcedureName @idx", param);
return result.FirstOrDefaultAsync().Result;

리스트 반환
context.Database.SqlQuery("GetPerson").AsQueryable();

Output parameter
var param = new SqlParameter { ParameterName = "idx", Value = 1 };
var output_param = new SqlParameter { ParameterName = "ResultCode", Value = 0, Direction = ParameterDirection.Output };
var result = context.Database.SqlQuery("GetPersons @idx, @ResultCode out", param, output_param).AsQueryable();

var resultCode = (int)output_param.Value;

위도(Latitude)와 경도(Longitude) 값을 이용한 거리계산



public double GetDistance(double lat1, double lon1, double lat2, double lon2)
        {
            double theta, dist;
            theta = lon1 - lon2;
            
            dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1))
                 * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
            dist = Math.Acos(dist);
            dist = rad2deg(dist);

            dist = dist * 60 * 1.1515;
            dist = dist * 1.609344;    // 단위 mile 에서 km 변환.  
            dist = dist * 1000.0;      // 단위  km 에서 m 로 변환  

            return dist;
        }
        /// 
        /// 주어진 Degree 값을 Radian 값으로 변환
        /// 
        /// Degree
        /// Radian
        private double deg2rad(double deg)
        {
            return (double)(deg * Math.PI / (double)180d);
        }
        /// 
        /// 주어진 Radian 값을 Degree 값으로 변환
        /// 
        /// Radian value
        /// Degree
        private double rad2deg(double rad)
        {
            return (double)(rad * (double)180d / Math.PI);
        }

2015년 9월 3일 목요일

C# GUID



GUID : 사용할 수 있는 값의 수가 2120  임으로 적절한 알고리즘이 있다면 같은 값을 두번 생성 할 가능성은 매우 적다.

생성방법 :
    GUID guid = GUID.NewGuid()


출력예(36자) : 95267ea6-5bfe-47db-8794-7e08404672c3

2015년 8월 29일 토요일

소스코드 실행 시간 확인 Stopwatch



 Stopwatch stopwatch = Stopwatch.StartNew();
       ..............................

stopwatch.Stop();
Console.WriteLine("실행시간 : ", stopwatch.ElapsedMilliseconds);

2015년 5월 21일 목요일

C# Get Clinent MacAddress




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using System.Net.NetworkInformation;

namespace test
{
    public static class MacAddress
    {
        public static string GetMacAddress()
        {
            const int MIN_MAC_ADDR_LENGTH = 12;
            string    macAddress          = string.Empty;
            long      maxSpeed            = -1;

            foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
            {
                string tempMac = nic.GetPhysicalAddress().ToString();
                if (nic.Speed > maxSpeed && !string.IsNullOrEmpty(tempMac) && tempMac.Length >= MIN_MAC_ADDR_LENGTH)
                {
                    maxSpeed   = nic.Speed;
                    macAddress = tempMac;
                }
            }
            return macAddress;
        }
    }
}

2013년 9월 28일 토요일

DbArithmeticExpression arguments must have a numeric common type.

DbArithmeticExpression arguments must have a numeric common type.

if (oders.Count() > 0) point = oders.Where(o => (DateTime.Now - o.ShipDate).Days > 7);
위 코드를 아래와 같이 수정하면 된다.
if (oders.Count() > 0) point = oders.Where(o => EntityFunctions.DiffDays(o.ShipDate, DateTime.Now) > 7);

2013년 8월 30일 금요일

확장메서드

확장 메서드의 세가지 선언 규칙
  • static 클래스 안에 구현되어야 한다.
  • static 메서드로 선언되어야 한다.
  • 항상 첫 번째 파라미터에는 본인이 포함될 타입을 지정한다. 그리고 지정된 타입 앞에는 this 키워드가 위치해야 한다.
public static class ExtensionString
{
    public static string LongStringLimit(this StringBuilder src, int limitLength)
    {
        string limit = src.ToString();
 
        if (src != null) src = null;
        if (limit.Length <= limitLength) return limit;
        else 
        {
            limit = limit.Substring(0, limitLength);
            return String.Format("{0}...", limit);
        }
    }
}

Execute CRUD-LINQ

ExecuteCommand : 요청할 쿼리문과 쿼리문에 적용할 파라미터를 전달받아 실행하고 실행 결과를 int 타입으로 리턴한다.
                                이 값은 쿼리문이 실행된 이후에 영향받은 데이터 건수를 가진다.

Select


IEnumerable<Products> result = north.ExecuteQuery<Products>
            ("Select * from products where unitprice >= {0}", 100);
foreach(Products prod in result)
{
    Console.WriteLIne("ProductID : {0}, Unit Price : {1}", 
                      prod.ProductID, 
                      prod.UnitPrice);
}

Insert, Update, Delete

public void ExecuteCommandTest()
{
    const string insertProd = "insert into products values({0}, {1}, {3}, {4}, {5})";
    const string updateProd = "update products set UnitPrice = UnitPrice + 2.00 where UnitPrice >= {0}";
    const string deleteProd = "delete products where unitprice >= {0}";
 
    try
    {
        int insertAffectedCnt = north.ExecuteCommand(insertProd, "Test Prod",
                                                     10,         1,
                                                     "31 boxes", 7.00,
                                                     61);
        int updateAffectedCnt = north.ExecuteCommand(updateProd, 100);
        int deleteAffectedCnt = north.ExecuteCommand(deleteProd, 100);
  
        //변경 사항을 데이터베이스에 반영
        north.SubmitChanges();
 
        //추가, 수정, 삭제 처리 후 영향받은 데이터 건수 체크
        Console.WriteLine("추가된 건 수 : {0} 수정된 건 수 : {1} 삭제된 건 수 : {2}",
                      insertAffectedCnt, updateAffectedCnt, deleteAffectedCnt);
    }
    catch(Exception ex){ Console.WriteLine(ex.Message); }
}

저장프로시저와 함수 - LINQ

저장프로시저를 이용한 다중테이블 입력 방법
예 : Customers와 CustomersInfo 두 테이블 있고 회원가입시
       Customers에는 UserName, Password, Email을 입력하고
       CustomerInfo에는 FullName과 Customers에 Primary Key인 CustomerID를 입력한다면

DB에 Stored Procedure 생성

CREATE PROCEDURE [InsertCust]
@Username VARCHAR(10),
@Password CHAR(40),
@Email VARCHAR(100),
@Fullname NVARCHAR(10)
AS
DECLARE @CustomerID INT;
BEGIN TRY
    INSERT INTO [Customers] VALUES(@Username, @Password, @Email);
    SELECT @CustomerID = [CustomerID] FROM [Customers] WHERE [UserName] = @Username;
    INSERT INTO [CustomerInfo]([CustomerID], [FullName]) VALUES(@CustomerID, @Fullname);
END TRY

BEGIN CATCH
    RETURN ERROR_NUMBER()
END CATCH
GO

Entity설정

[Function(Name="dbo.InsertCust")]
public int InsertCust(
    [Parameter(Name="Username",DbType="VarChar(10)")] string username,
    [Parameter(Name="Password",DbType="Char(40)")]    string password,
    [Parameter(Name="Email",DbType="VarChar(100)")]   string email,
    [Parameter(Name="FullName",DbType="NVarChar(30)")]string fullname)
    {
        IExecuteResult result = this.ExecuteMethodCall(
        this,
        ((MethodInfo)(MethodInfo.GetCurrentMethod())),
        username, password, email, fullname);
    return ((int)(result.ReturnValue));
}

사용방법

CustomersEntity entity = new CustomersEntity(conn);
int insert = entity.InsertCust("tomebody", "han001122", "tome@naver.com", "Tome kim");
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

저장프로시저를 이용한 다중테이블 조회 방법
예 : CustomerInfo, Products, Orders 3개의 테이블이 있다고 가정
       CustomerInfo에서는 FullName,
       Products에서는 ProductName,
       Orders에서는 UnitPrice, Amount를 읽어온다.
       단 CustomerID, ProductID를 기준값으로

DB에 Stored Procedure 생성


CREATE PROCEDURE [SelectOrderInfo] @CustomerID INT, @ProductID INT
AS
    SELECT c.FullName, p.ProductName, o.Quantity, (o.Quantity * p.UnitPrice) AS [Amount]
    FROM [CustomerInfo] c
    JOIN [Orders] o
    On c.CustomerID = o.CustomerID
    JOIN [Products] p
    On o.ProductID = p.ProductID
    WHERE c.CustomerID = @CustomerID And o.ProductID = @ProductID
GO

Entity설정


[Function(Name="dbo.SelectOrderInfo")]
public ISingleResult<SelectOrderInfoResult> SelectOrderInfo(
    [Parameter(Name="CustomerID",DbType="Int")]int CustomerID,
    [Parameter(Name="ProductID",DbType="Int")]int ProductID)
{
    IExecuteResult result = this.ExecuteMethodCall(
        this,
        ((MethodInfo)(MethodInfo.GetCurrentMethod())),
        CustomerID, ProductID);
    return((ISingleResult<SelectOrderInfoResult>)(result.ReturnValue));
}

public partial class SelectOrderInfoResult
{
    [Column]public string FullName { get; set; }
    [Column]public string ProductName { get; set; }
    [Column]public int Quantity { get; set; }
    [Column]public int Amount { get; set; }
}
SelectProcedure entity = new SelectProcedure(conn);

Entity설정

ISingleResult<SelectOrderInfoResult> Result = entity.SelectOrderInfo(1, 1);
foreach (SelectOrderInfoResult item in Result)
{
    Console.WriteLine("{0}-{1}-{2}-{3}",
        rs.FullName,
        rs.ProductName,
        rs.Quantity,
        rs.Amount);
}

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
ISingleResult<TEntity> : 저장 프로시저의 실행 결과로 리턴되는 엔티티 클래스의 단일 결과집합을 가진다.

델리게이트와 익명 메서드

C#에서 델리게이트는 delegate라는 키워드를 통해 선언되며 리턴 타입과 파라미터도 가질 수 있다. 또한 new 연산자를 통해 인스턴스를 생성하여 사용된다. 델리게이트가 갖는 리턴 타입과 파라미터는 그가 처리하는 메서드에 종속적이다.
대리자는 메서드를 다른 메서드에 인수로 전달하는데 사용된다.

예
// Declare delegate -- defines required signature:
delegate double MathAction(double num);

class DelegateTest
{
    // Regular method that matches signature:
    static double Double(double input)
    {
        return input * 2;
    }

    static void Main()
    {
        // Instantiate delegate with named method:
        MathAction ma = Double;

        // Invoke delegate ma:
        double multByTwo = ma(4.5);
        Console.WriteLine(multByTwo);

        // Instantiate delegate with anonymous method:
        MathAction ma2 = delegate(double input)
        {
            return input * input;
        };

        double square = ma2(5);
        Console.WriteLine(square);

        // Instantiate delegate with lambda expression
        MathAction ma3 = s => s * s * s;
        double cube = ma3(4.375);

        Console.WriteLine(cube);
    }
}


List<int> list = new List<int>();
list.AddRange(new int[] { 100, 200, 300, 400, 500, 600 });
ICollection<int> result = list.FindAll(delegate(int item) { return item > 350; });
foreach (int a in result)
{
    Console.WriteLine(a);
}

제네릭 형식 정의와 사용

1. using System.Collections.Generic
2. 제한 사항과 제약 사항
   
제한사항 
  1. 제네릭이 적용된 클래스는 ContextBoundObject 클래스로부터 파생될 수 없다.
  2. 열거형에 사용될 수 없다.
  3. Replection을 이용해서 생성되는 동적 메서드는 제네릭 형식을 취할 수 없다.
 -제약사항 : 제네릭 클래스 레벨에서 선언될 경우 선언하는 클래스에 몇 가지의 제약 사ㅏ항을 지정할 수 있다.  이 제약 사항은 SQL문에서 where절에서 사용하는 것과 의미가 동일하다.
예 :

//IDisposable을 구현하는 T
class GenericConstraint<T> where T : IDisposable{}
//class 타입 T, 구조체 타입 U
class GenericConstraint<T, U> where T : class where U : struct{}
//IComparable을 구현하고, 파라미터가 없는 기본 생성자를 가진 타입 T
class GenericConstraint<T> where T : IComparable, new()

//델리게이터에 파라미터가 없는 기본생성자를 가진 타입 T
delegate T GenericDelegate<T>(T val) where T : new();

Dictionary<TKey, TValue>
Dictionary<int, string> colorDic = new Dictionary<int, string>();
//key와 value를 쌍으로 저장
colorDic.Add(1, "Red");
//값 변경
colorDic[1] = "Black";
//key가 3인 color 값 조회
string blackColor = string.Empty;
if(colorDic.TryGetValue(3, out blackColor))
{
    Console.WriteLine("key가 3으로 저장된 Color는 {0}", blackColor);
}
//key가 4인 데이터 존재 유무 확인
if(!colorDic.ContainsKey(4))
{
    colorDic.Add(4, "Yellow");
}
//key값만 가지는 컬렉션 객체 생성
Dictionary<int, string>.KeyCollection keyCollection = colorDic.Keys;
foreach(int key in keyCollection)
{
    Console.WriteLine(key);
}
//value값만 가지는 컬렉션 객체 생성
Dictionary<int, string>.ValueCollection valueCollection = colorDic.Values;
//key와 value를 쌍으로 가지는 컬렉션의 요소 조회
foreach(KeyValuePair<int, string> keyValue in colorDic)
{
    Console.WriteLine("key {0}의 Color는 {1}", keyValue.Key, keyValue.Value); 
}
*TryGetValue 메서드는 key값을 기준으로 해당 데이터를 out파라미터로 전달한다.
List<T>
예:
List<int> list = new List<int>();
list.Add(100);
//컬렉션의 현재 배열 크기 조회
Console.WriteLine("컬렉션의 현재 배역 크기는 {0}", list.Capacity);
//컬렉션의 현재 저장 데이터 개수 조회
Console.WriteLine("컬렉션에 저장된 요소의 개수는 {0}", list.Count);
//1번째에 데이터 저장
list.Insert(1, 500);
//1번째에 저장된 데이터 조회
Console.WriteLine("1번째 데이터는 {0}", list[1]);
//1번째에 데이터 삭제
list.RemoveAt(1);
//컬렉션의 배열 크기를 조정
list.TrimExcess();
TrimExcess() : 동적 배열 크기를 갖는 클래스에서 공통적으로 사용되는 메서드로 호출후의 배열 크기는 컬렉션에 저장되어 있는 요소의 개수와 동일해 진다.
SortedList<TKey, TValue>
예:
// 컬렉션 인스턴스 생성
SortedList<int, string> colorSort = new SortedList<int, string>();
// 데이터 저장
colorSort.Add(1, "Red");
colorSort.Add(3, "Green");
colorSort.Add(2, "Blue");
// 저장된 데이터 조회
foreach (KeyValuePair<int, string> color in colorSort)
{
    Console.WriteLine(color.Value);
}
// 컬렉션의 배열 크기 조회
Console.WriteLine("현재 컬렉션의 배열 크기 : {0}", colorSort.Capacity);
// 컬렉션 배열 크기 조정
colorSort.TrimExcess();
// 첫 번째 배열 크기 및 요소 개수 조회
Console.WriteLine("첫 번째 TrimExcess 호출 후 컬렉션 배열 크기:{0}, 요소 개수:{1}", colorSort.Capacity, colorSort.Count);
// key 값이 2인 데이터 삭제
colorSort.RemoveAt(2);
// 컬렉션 배열 크기 조정
colorSort.TrimExcess();
// 두 번째 배열 크기 및 요소 개수 조회
Console.WriteLine("두 번째 TrimExcess 호출 후 컬렉션 배열 크기:{0}, 요소 개수:{1}", colorSort.Capacity, colorSort.Count );

LinkedList<T>
Queue<T>
Stack<T>

C# String & 정규식




string.Replace(‘원본’,’교체’)
string.Insert(‘Index’, ‘삽입할 데이터’)
string.Substring(‘start_index’, ‘end_index’)
string.StartsWith(‘MachingString’)

{N[,M][:formatString]}
N 0부터 시작하는 인덱스값으로 대치될 인수를 나타낸다.
M 값은 대치될 값이 표시될 자리 수를 나타낸다. 만약 인수의 길이가 이 M 값보다 작으면 공란이 포함되어 표시된다.

   만약 M값을 음수로 지정하면 대치되는 인수는 왼쪽 정렬로 표시되고, 만약 M 값을 양수로 지정하면 오른쪽 정렬로

   표시된다.
formatString 선택 포맷 코드 string이다.

문자형식
C or c  통화
D or d10진법
E or e공학용(지수)
F or f고정 소수점
G or g일반
N or n번호, 이와 비슷한 F는 천 단위마다 컴마가 추가된다.
P or p퍼센트
R or r라운드 트립, string으로 변경된 numeric 타입이 원래의 numeric값으로 원 위치될 수 있게 보장한다. 부동소수점일 때만 지원한다.
X or x



/////////////////////////////////////////////////////////////////////
int i = 123456;
{0:C} : $123456 {0:C5} : $123456.00000
{0:D} : 123456 {0:D5} : 123456
{0:E} : 1.234560E+005 {0:E5} : 1.234560E+005
{0:F} : 123456.00 {0:F5} : 123456.00000
{0:G} : 123456 {0:G5} : 123456
{0:N} : 123,456.00 {0:N5} : 123,456.00000
{0:P} : 12,345,600.00 % {0:P5} : 12,345,600.00 %
{0:X} : 1E240 {0:X5} : 1E240
/////////////////////////////////////////////////////////////////////


형식문자사용 용도설명
00자리 표시자 표시숫자가 형식상 0보다 적은 숫자라면 nonsignificant 0으로 표시
#숫자 자리 표시자 표시파운드 표시(#)를 significant숫자로만 대체
.10진수의 점을 표시마침표 표시
,그룹 구분자1,000처럼 숫자 즈룹을 구분
%퍼센트 표시퍼센트(%) 표시
E+0
E-0
e+0
e-0
지수 표시지수 결과 형식으로 표시
\문자 표시“\n”처럼 전통적인 형식 시퀀스와 함깨 사용
‘ABC’문자 string따옴표나 쌍따옴표 내에 모둔 종류의 string 표시
;부분 구분자숫자값이 양수, 음수, 0에 따라 다른 결과값을 지정


/////////////////////////////////////////////////////////////////////
int i = 123456     
{0:#0}   123456
{0:#0;(#0)}    123456
{0:#0;(#0);<zero>} 123456
{0:#%} 12345600%

int j = -123456   
{0:#0}   -123456
{0:#0;(#0)}    (123456)
{0:#0;(#0);<zero>} (123456)
{0:#%} -12345600%

int x = 0
{0:#0}   0
{0:#0;(#0)}    0
{0:#0;(#0);<zero>} <zero>
{0:#%} %
/////////////////////////////////////////////////////////////////////
StringBuilder
.Replace(‘원본’, ‘교체’)
.Insert(index, ‘data’)
.Append(‘data’)
.AppendFormat(“{0:3}”, ‘data’)
.Remove(start_index, end_index)

정규식
설명
.“\n”이외의 모든 단일 문자를 찾는다.
[characters]목록에서 단일 문자를 찾는다.
[^characters]목록에 없는 단일 문자를 찾는다.
[charX-charY]지정된 범위에서 단일 문자를 찾는다.
\w[a-zA-Z_0-9]와 같은 단어 문자를 찾는다.
\W단어가 아닌 문자를 찾는다.
\s[\n\r\t\f]와 같은 공백 문자를 찾는다.
\S공백이 아닌 문자를 찾는다.
\d[0-9]와 같은 10진수를 찾는다.
\D숫자가 아닌 문자를 찾는다.
^줄 시작
$줄의 마지막
\b단어 경계
\B단어 경계가 아닌 부분
*0개 이상 찾는다.
+1개 이상 찾는다.
?0개나 한 개 찾는다.
{n}정확히 n개 찾는다.
{n,}최소한 n개인 것을 찾는다.
{n,m}최소 n개 최대 m개인 것을 찾는다.
()일치하는 substring을 캡처한다.
(?<name>)일치하는 substring을 그룹 이름으로 캡처한다.
|논리적 OR


Match
static void Main(string[] args)
{
    Regex r = new Regex(“in”);
    Match m = r.Match(“Matching”);
    if(m.Success)
    {
        Console.WriteLine(“Found ‘{0}’ at position {1}”, m.Value, m.Index);
    }
}


String에 패턴이 여러 번 발생된다면 …
static void Main(string[] args)
{
    Regex r = new Regex(“in”);
    MatchCollection mc = r.Matches(“The King Was in His Counting”);
    for(int i = 0; i < mc.Count; i++)
    {
        Console.WriteLine(“{0}-{1}”, mc[i].Value, mc[i].Index);
    }
}
또는 
static void Main(string[] args)
{
    Regex r = new Regex(“in”);
    string str = “The King Was in His Counting”;
    Match m;
    for(m = r.Match(str); m.Success; m = m.NextMatch())
    {
        Console.WriteLine(“{0}-{1}”, mc.Value, mc.Index);
    }
}
여러 패턴의 인스턴스에 대한 일치 : Regex r = new Regex(“((an)|(in)|(on))”);
여러 패턴의 인스턴스에 대한 일치 : Regex r = new Regex(“Gr(a|e)y”);

Groups
Group클래스는 그룹과 일치하는 하나의 정규식 결과를 표시한다.Match클래스는 GroupCollection 객체를 반환하는 Groups 프로퍼티를 제공한다.
static void Main(string[] args)
{
    Regex r = new Regex(“(i(n))g”);
    string str = “The King Was in His Counting”;
    Match m = r.Match(str);
    GroupCollection gc = m.Groups;

    for(int i = 0; i < gc.Count; i++)
    {
        Group g = gc.[i];
        Console.WriteLine(“Found ‘{0}’ at position {1}”, g.Value, g.Index);
    }
}
Group
Regex q = new Regex(“(?<something>\\w+):(?<anogher>\\w+)”);
Match n = q.Match(“Salary:123456”);
Console.WriteLIne(“{0} = {1}”, n.Groups[“something”].Value, n.Groups[“another”].Value);

//?<another>\\w+ 일치하는 substring을 단어문자만 ‘another’이라는 그룹에 캡처한다.

Captures
msdn.microsoft.com/ko-kr/library/system.text.regularexpressions.capture(VS.95).aspx
.Replace(“string”, “pattern”, “change_string”)
string s = “trailing “;
string e = @”\s+$”;
string r = Regex.Replace(s, e, “”);
>