ラベル C# の投稿を表示しています。 すべての投稿を表示
ラベル C# の投稿を表示しています。 すべての投稿を表示

2010年9月24日金曜日

Project Euler(その2)

image

今日も引き続き挑戦してました。18問目まで終了。

12問目がなかなか計算時間短縮が難しい。

2010年9月23日木曜日

Project Euler

Project Eulerなるものを知った。数学の問題をプログラムで解くらしい。
おもしろそうなので、登録してみた。
#そういえば、TopCoderに登録してそのままなことを思い出した。
http://projecteuler.net/

日本語のWikiもあり、問題も日本語化されているようだ。<やった。
http://odz.sakura.ne.jp/projecteuler/index.php?Project%20Euler

番号が若いうちは比較的簡単。出来るだけLinqを使って書くように心がける。
#でもLinqだと無駄が出やすい気がする。スピード重視なら、手続き指向になるのかなぁ。

image

とりあえず、今日は8問目まで。

2010年6月1日火曜日

スカラプロパティーに外部キーを追加する

Entity Framework4では、外部キーをスカラプロパティーとして公開することが出来ます。

外部キーの使用 (Entity Framework)
http://msdn.microsoft.com/ja-jp/library/ee794150.aspx

でも、追加方法がよくわからずはまったので備忘録。

①追加からアソシエーションを選択すること。
(ツールボックスからではダメ。ここではまった。)
image

②外部キープロパティーの追加にチェックを付ける
 image
③プロパティーが追加されます。
image 

ところで、追加されたプロパティーが、どのアソシエーションに関連しているかを確認する方法がない?

2010年5月20日木曜日

WPFとWinForm

@ITにて、WPFの連載とWinFormの連載がほぼ同時にスタート。

連載:Windowsフォーム開発入門【Visual Studio 2010対応】
http://www.atmarkit.co.jp/fdotnet/chushin/introwinform_index/index.html
連載:WPF入門
http://www.atmarkit.co.jp/fdotnet/chushin/introwpf_index/index.html

いよいよ全面対決か?
何度も途中で挫折しているので、WPFもう一回最初っから勉強し直そうかな。

2010年5月1日土曜日

x64環境のOLEDBドライバ

長らくx64環境からMDBファイルにアクセスすることが出来なかった。
(正しくは、32bitアプリとしてWOW64上で動作する様に、ビルド構成としてx86を指定する必要があった。)

Office2010(x64)をインストールすることにより、64bitのアプリケーションでもMDBファイルにアクセスできるようになる。ConnectionStringで”Microsoft.ACE.OLEDB.12.0”するだけである。

データ接続コンポーネントも、今はベータがとれていないが、そのうちベータがとれるだろう。
(2010 Office system Beta ドライバ: データ接続コンポーネント)
http://www.microsoft.com/downloads/details.aspx?familyid=C06B8369-60DD-4B64-A44B-84B371EDE16D&displaylang=ja

これにより、32bitでは"Microsoft.JET.OLEDB.4.0"、64bitでは"Microsoft.ACE.OLEDB.12.0”と接続文字列を切り替えることにより、どちらの環境でも動作させることが可能になる。
※32bitでも下記ドライバをインストールすれば、"Microsoft.ACE.OLEDB.12.0”で接続が可能。
2007 Office system ドライバ: データ接続コンポーネント
http://www.microsoft.com/downloads/details.aspx?FamilyId=7554F536-8C28-4598-9B72-EF94E038C891&displaylang=ja

なお、32bitで動作しているか64bitで動作しているかは、IntPtr.Sizeで判定が可能だそうだ。

(とあるコンサルタントのつぶやき:Part 2. .NET Framework 2.0 アプリケーションの 64 ビット対応)
http://blogs.msdn.com/nakama/archive/2008/11/06/part-2-net-framework-2-0-64.aspx

なお、アプリケーションの内部から、現在自分が 64 ビット/32 ビットどちらで動作しているのかを知る一番簡単な方法は、IntPtr.Size プロパティをチェックするというものです。

  • IntPtr.Size = 8 の場合は 64 ビットモードでプロセスが動作している。
  • IntPtr.Size = 4 の場合は 32 ビットモードでプロセスが動作している。

2010年4月14日水曜日

PLinq

Visual Studio 2010(.NET Framework 4)より、PLINQ (Parallel LINQ)が追加され、並列処理が簡単にできるようになっています。

10 行でズバリ !! 並列プログラミング - PLINQ (C#)より
PLINQ は LINQ によるデータ コレクションに対するクエリ処理を並列化するためのものであり、PLINQ を使用することで LINQ クエリの Select 句や Where 句で実行されるロジックを容易に並列処理化することが可能です。PLINQ の機能は ParallelEnumerable クラス (System.Linq.ParallelEnumerable) の拡張メソッドとして提供されており、LINQ クエリの処理対象データ コレクションに対して ParallelEnumerable クラスの拡張メソッドの呼び出しを追加するだけでデータ コレクションへの処理を並列化し、マルチプロセッサー/マルチコア CPU の処理能力を活用して処理時間を短縮することができます。

と言うわけで、先日の重いLinq構文を何とか出来ないかとあちこちにAsParallelを追加してみました。
が、Aggregate構文を途中で使用しているためか、追加前より速くなることはありませんでした。
残念。

2010年4月8日木曜日

順列の問題

0~9までの数字のカードがN枚ある。同じ数字のカードは1枚とは限らない。
そこから、M枚使用しM桁の整数を作るとき、小さい方から数えi番目の数値は何か?
※先頭桁に0はこないものとする。

という問題が与えられた場合、これを効率よく説くにはどうすればよいか?

とりあえず、効率よくという部分は無視して、順列を作成して前から数えてみた。順列を作成するに当たりLinqを使用しているサイトが見つかったので、利用にさせていただいた。
http://d.hatena.ne.jp/taguo/20080722/1216745650

class Program
{
static void Main(string[] args)
{
int[] array = {0,0,1,2,2,3};
var result = array.GetPermutation(4)
.Where(x => x.ElementAt(0) != 0)
.Select(x => string.Join("", x.Select(i => i.ToString()).ToArray()))
.Distinct();

result = result.Skip(10).Take(1);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
}

public static class Util
{
public static IEnumerable<IEnumerable<T>> GetPermutation<T>(this IEnumerable<T> source, int count)
{
return Enumerable.Range(0, count)
.Select(_ => source)
.Select(et => et.Select((t, i) => new { t, i }))
.Aggregate(Enumerable.Repeat(Enumerable.Repeat(new { t = default(T), i = default(int) }, 0), 1)
, (ac, et) => from a in ac
from t in et
where !a.Contains(t)
select a.Concat(Enumerable.Repeat(t, 1)))
.Select(ea => ea.Select(a => a.t));
}
}

2010年4月3日土曜日

delegate-非同期呼出

実は、delegateの非同期呼出は使ったことがなかったり…
というわけで、MultiCastDelegateといえどもターゲットが複数あるとダメなのは初めて知りました。
image 
出来ても良さそうなのにね。

2010年4月1日木曜日

delegate-同期呼出

delegateは、メソッド情報(Methodプロパティー)を呼びメソッドの定義されるインスタンスの情報(Targetプロパティー)を持ち、それを同期または非同期に呼び出すことができる。

というわけで、まずは同期呼出から。とっても基本的な使い方。

delegate void Hoge(string str);

static void Main(string[] args)
{
Hoge hoge = null;

hoge = Console.WriteLine;

hoge("AAA");
hoge.Invoke("AAA");
}

9行目と10行目はどちらも同じILがはき出され、この場合、Console.WriteLineが実行される。

delegateで宣言すると、MultiCastDelegateのサブクラスとなるので、常にInvocation Listを作ることが可能。

static void Main(string[] args)
{
Hoge hoge = null;

hoge = Console.WriteLine;
hoge += delegate(string str)
{
Console.WriteLine(str.ToLower());
};

hoge("AAA");
}

メソッドはデリゲートに登録された順番に順次実行されていく。また、+=演算子はDelegate.Combineに置き換えられる。

メソッドの引数は同じオブジェクトが順番に渡されるため、1番目のメソッドで行われた変更を2番目のメソッドへと引き継ぐ。MultiCastDelegateの場合、最後のメソッドの戻り値以外は捨てられるので、引数のオブジェクトを通してしか情報の伝達ができない。

class Program
{
//戻値の型 デリゲートの型名 引数の型
delegate void Hoge(Class c);

static void Main(string[] args)
{
Hoge hoge = null;

hoge += AAA;
hoge += AAA;
hoge += AAA;
hoge += AAA;

hoge(new Class());
}

static void AAA(Class c)
{
Console.WriteLine(c.MyProperty);
++c.MyProperty;
}
}


class Class : Interface
{
public int MyProperty { get; set; }
}

delegate

delegateはC#の言語をもっとも特徴付ける者だと思ってる。
#といってもC#以外はJavaぐらいしか知らないけど…それも1.4

というわけでdelegate再入門

//戻値の型 デリゲートの型名 引数の型
delegate void Hoge(string str);

引数の変数名は余分な気がするが、上記のように宣言することで、MultiCastDelegateを継承した独自型が生成される。

image
上記、delegateの宣言をReflectorで見た様子。
BeginInvokeメソッドの引数と、Invokeメソッドの引数および戻値は、delegateの宣言時の型が使用される。

2010年3月27日土曜日

Interfaceは参照型

Interfaceは参照型だったよな。と思い確認。

class Program
{
static void Main(string[] args)
{

Struct s = new Struct();
s.MyProperty = 1;

Interface i = s;
i.MyProperty = 2;

Interface i2 = i;
i2.MyProperty = 3;

Console.WriteLine("s :{0}", s.MyProperty);
Console.WriteLine("i :{0}", i.MyProperty);
Console.WriteLine("i2:{0}", i2.MyProperty);
}
}

interface Interface
{
int MyProperty { get; set; }
}

struct Struct : Interface
{
public int MyProperty { get; set; }
}
結果
image

正解。

つまり、Interface型に代入する際にボックス化が行われているということ。

class Program
{
static void Main(string[] args)
{
var val = new Struct();
var val2 = new Class();

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000000; i++)
{
object obj = val;
}
Console.WriteLine("struct -> object :" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
Interface obj = val;
}
Console.WriteLine("struct -> Interface:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
var obj = val;
}
Console.WriteLine("struct -> struct :" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
Interface obj = val2;
}
Console.WriteLine("class -> Interface:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
object obj = val2;
}
Console.WriteLine("class -> object :" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
var obj = val2;
}
Console.WriteLine("class -> class :" + sw.Elapsed);


}
}

interface Interface
{
int MyProperty { get; set; }
}

struct Struct : Interface
{
public int MyProperty { get; set; }
}


class Class : Interface
{
public int MyProperty { get; set; }
}

image

2010年3月22日月曜日

boxing(ボックス化)

boxing(ボックス化)とは、値型を参照型であるobjectに変換する機能。
これにより、参照型であるobjectに値型を代入することができる。
ただし、パフォーマンス上の注意が必要。Generic型を使用することにより、boxingを防ぐことができる。

static void Main(string[] args)
{
var val = new Struct();
var val2 = new Class();

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000000; i++)
{
object obj = val;
}
Console.WriteLine("struct -> object:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
var obj = val;
}
Console.WriteLine("struct -> struct:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
object obj = val2;
}
Console.WriteLine("class -> object:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
var obj = val2;
}
Console.WriteLine("class -> class :" + sw.Elapsed);


var list = new List<Struct>(100000000);
var list2 = new List<Class>(100000000);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
list.Add(val);
}
Console.WriteLine("generic list <- struct:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
list2.Add(val2);
}
Console.WriteLine("generic list <- class :" + sw.Elapsed);

var list3 = new ArrayList(100000000);
var list4 = new ArrayList(100000000);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
list3.Add(val);
}
Console.WriteLine("normal list <- struct:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
list4.Add(val2);
}
Console.WriteLine("normal list <- class :" + sw.Elapsed);
}

struct Struct
{
public int MyProperty { get; set; }
}

class Class
{
public int MyProperty { get; set; }
}

image
違いは一目瞭然。

2010年3月21日日曜日

値型と参照型

EffectiveC#を読んで、基本に立ち返ってみた。

(参照渡)

class Program
{
static void Main(string[] args)
{
var val = new Class();
var val2 = val; //参照渡し

val.MyProperty = 100;

//100 が表示される
Console.WriteLine(val2.MyProperty);
}
}

class Class
{
public int MyProperty { get; set; }
}

classは参照型であり、代入は参照がコピーされる。なので、 valとVal2の指す実体は同じ。 
image

(値渡)

class Program
{
static void Main(string[] args)
{
var val = new Struct();
var val2 = val; //値渡し

val.MyProperty = 100;

//0 が表示される
Console.WriteLine(val2.MyProperty);

}
}

struct Struct
{
public int MyProperty { get; set; }
}

structは値型であり、代入はコピーが作成されるので、valを変更してもval2に影響はない。
image

2010年3月14日日曜日

DbDataSourceEnumerator

DbProviderFactoryから作成できる、DbDataSourceEnumerator。一度も使ったことがなかったので、使ってみた。

if (factory.CanCreateDataSourceEnumerator)
{
DbDataSourceEnumerator dse = factory.CreateDataSourceEnumerator();
dataGridView1.DataSource = dse.GetDataSources();
}
なかなか、CanCreateDataSourceEnumeratorプロパティーがTrueにならない。
どうやら、SQLClient(SQLServer用)でしか使えないっぽい(?)

Commonに必要か?

2010年3月13日土曜日

DbProviderFactory(その2)

前回の続き(?)。
Providerに依存しないコードを書いてみた。


ConnectionStringSettings css = ConfigurationManager.ConnectionStrings["MyConnection"];
DbProviderFactory factory = DbProviderFactories.GetFactory(css.ProviderName);

DbConnectionStringBuilder sb = factory.CreateConnectionStringBuilder();
sb.ConnectionString = css.ConnectionString;
//この辺はProviderに依存するよなぁ
sb.Add("Password", "xxxx");

using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = sb.ConnectionString;
connection.Open();
//factory.CreateCommand()でもいいけど、こっちの方が素直な気がする。
DbCommand command = connection.CreateCommand();

//ここも依存することが多いよね。
command.CommandText = "SELECT * FROM TABLE1 WHERE ID = ?";
DbParameter p = factory.CreateParameter();
p.DbType = DbType.Int32;
p.Value = 1;
command.Parameters.Add(p);

using (DbDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
reader.GetInt32(0);
}
}
}

DbProviderFactory

DbProviderFactoryを使用することにより、データプロバイダに依存しない実装が可能。で、備忘録

使用可能なProvider一覧を取得
DbProviderFactories.GetFactoryClasses();
machine.configより、DataProviderの情報を取得している。
戻り値はDataTable型なので、DataGridViewを使えば簡単に内容を確認することができる。
image

ApplicationでDataProviderを追加したい場合は、app.configに設定することで追加可能。 例えば、PostgreSQLの場合は、↓の様に設定。

<system.data>
<DbProviderFactories>
<add name="Npgsql Data Provider" invariant="Npgsql" description=".Net Framework Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.8.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
</DbProviderFactories>
</system.data>
そうすることで、DbFactoryが取得可能となる。
image

app.configよりConnectionStringを取得してDbProviderFactoryを作成 

ConnectionStringSettings css = ConfigurationManager.ConnectionStrings["MyConnection"];
DbProviderFactory factory = DbProviderFactories.GetFactory(css.ProviderName);
ConfigurationManagerからConnectionStringSettingsを取得。(System.Configuration.dllの参照が必要)
ConnectionStringSettingsよりProviderNameを取得し、DbProviderを作成

あとは、factory.CreateXXXXX()で作成し放題!

2009年12月22日火曜日

ADO.NET Entity Framework Sample Provider

以前より、Linqを利用しMDBファイルにアクセスする方法をもさくしている。

いろいろ検索しているうちに、ADO.NET Entity Frameworkにて、独自のProviderを実装する方法を紹介しているページを発見。
http://blogs.msdn.com/adonet/archive/2007/03/16/ado-net-orcas-sample-provider.aspx
#だが英語

MSDNのCode Gallery内で、サンプルとOracle版は公開されているようだ。
http://code.msdn.microsoft.com/EFSampleProvider
http://code.msdn.microsoft.com/EFOracleProvider
これを参考にOleDBをWrappeingするProviderを作ればいいのか?
誰か作っててもいいのに…

2009年12月21日月曜日

Linq to SQL

世間では.NET4.0がリリースされようとしている昨今。今更ながらLinq to SQL の勉強です。
Linq to SQLは、ADO.NET Entity Frameworkに取って代わられるとか言われてますが、気にしない。

(参考リンク)
http://msdn.microsoft.com/ja-jp/library/bb425822.aspx

上記ページでどうしても納得いかない箇所が…。DataContextにTable<T>を定義して、それに対してLinqでクエリを投げている箇所。

public partial class Northwind : DataContext
{
public Table<Customer> Customers;
public Table<Order> Orders;
public Northwind(string connection): base(connection) {}
}
Northwind db = new Northwind("c:\\northwind\\northwnd.mdf");
var q =
from c in db.Customers
where c.City == "London"
select c;
foreach (var cust in q)
Console.WriteLine("id = {0}, City = {1}",cust.CustomerID, cust.City);

DataContextにTable<Customer>をフィールドとして定義しているだけで、いつの間にか値が代入されている。おそらく、コンストラクタ内でリフレクションを使用して代入しているのだろうが、わかりにくい。

2009年9月23日水曜日

Silverlightを試す

前々からずっと気になっていたんですが、なかなか試す機会がなかったで連休を利用してチャレンジです。

用意したもの

始める

VisualStudio1
上記をインストールすると、VisualStudioにSilverlight用のプロジェクトテンプレートが追加されていました。
とりあえず、Silverlightナビゲーションアプリケーションを選択(サンプルプロジェクトぽかったので)。

Dialog
するとダイアログが出てきて、何かを尋ねます。意味がわかってないので、デフォルトで。

IE
作成されたプロジェクトを、そのまま実行した結果。をを、うごいてますな。

Blend
画面レイアウトはBlendで編集するとのことなので、先ほどVisualStudioで作成されたプロジェクトをBlendで開いてみる。
そうすると、なぜがMainPage.xamlがエラーをはいています。なぜ?

キャプチャ
原因は、XAMLに書かれた日本語が文字化けして、"(ダブルクォーテーション)が消えてることでした。
文字コードが違うみたい。どこかで文字コードを設定する箇所があるのでしょうか?

で、ここで詰まってます。先は長い。

(追記)

image 
Blend上でファイルを右クリック→外部で編集。メモ帳でファイルが開くので、そのまま上書き保存。

image
そうすると、Blend側で上記ダイアログが表示され、ファイルの再読み込みを促される。
はいをクリックすると、エラーが解決する。一度解決したファイルは次からは正しく表示される。
XAMLファイルの数だけ上書き作業を行うとOK?なのかも。

なぜでしょうね。

2009年9月19日土曜日

フィボナッチ数列

Linqから使用しやすい数列を作成する勉強第1弾。
今更ながらなLinqなのですが、.NET Framework3.5はまだ仕事で使えない(※)ので、まだまだ詳しくありません。
ちょっとずつ勉強予定です。

public static IEnumerable<decimal> Fibonacci()
{
    decimal previous = 0M;
    decimal current = 1M;
    while (true)
    {
        yield return current;
        current += previous;
        previous = current - previous;
    }
}

として、

var fs = from f in EnumerableUtil.Fibonacci()
        where f % 3 == 0
        select f;
    foreach (var item in fs)
    {
        Console.WriteLine(item);
    }

こんな感じかね。

※Windows2000上で、.NET Framework3.5が動かないからなぁ。