泥庭

2016年11月2日

[C#読書会]日付時刻のソート

Filed under: .NET, C#, 読書会, 未分類 — yone64 @ 11:26 PM
ちょっと間が空きました。今回は4.4です。三日坊主すら難しいですね。
日付のソートのお話

(more…)

広告

2016年10月28日

[C#読書会]コレクションの初期化構文

Filed under: .NET, C#, 読書会 — yone64 @ 1:30 AM
前回の続きです。今回は4.4。
コレクション初期化子を使おうというお話。

(more…)

2016年10月27日

[C#読書会]TryGetでtryブロック追放

Filed under: .NET, C#, 読書会 — yone64 @ 12:39 AM
久々です。
最近、C#読書会なるもので、「C#ショートコードプログラミング」を読んでいます。
ので、軽く感想とか((続くかなぁ?

(more…)

2015年7月24日

【C#6.0】ラムダ式本体によるメンバーの記述

Filed under: .NET, C# — タグ: , , — yone64 @ 1:54 PM
今日は、ラムダ式本体によるメンバーの記述です。ながい。
# 拍子抜けするほどはまりどころがないので、さらさらいくよ。

(more…)

2015年7月22日

【C#6.0】nameof

Filed under: .NET, C# — タグ: , — yone64 @ 12:09 PM
シリーズものが続かないBlogですが、第2回。
今度はnameofを見ていきます。

(more…)

【C#6.0】プロパティー新機能

Filed under: .NET, C# — タグ: , — yone64 @ 12:03 AM
Visual Studio 2015が、無事(?)リリースされました。というわけで、C#6.0絡みの新機能を試してみた記録を残しておきます。
とりあえず、プロパティー周りから。
# C#6.0の新機能とか、あちこちで以前から書かれているので、特に新しい情報はないと思われ。

(more…)

2015年3月10日

【ReactiveProperty】きちんとDisposeしよう

Filed under: .NET, C#, WPF — タグ: , , , — yone64 @ 3:05 PM
ReactivePropertyが依存しているReactiveExtensionsのお話なのですが、きちんとにDisposeしないと予期しない動作の原因になります。

下記サンプル
MainWindow.xaml
<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Viewbox>
            <TextBlock Text="{Binding DateTime.Value}" />
        </Viewbox>
    </Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication3
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private IDisposable _disposable;

        public MainWindow()
        {
            InitializeComponent();

            var vm = new MainViewModel();
            this.DataContext = vm;

            this._disposable = vm as IDisposable;
            this.Closing += (s, e) =>
            {
                if (this._disposable != null) this._disposable.Dispose();
            };
        }
    }
}
MainViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using Reactive.Bindings;
 
namespace WpfApplication3
{
    public class MainViewModel : IDisposable
    {
        public ReactiveProperty<string> DateTime { get; private set; }
 
        public MainViewModel()
        {
            this.DateTime = 
                Observable.Interval(TimeSpan.FromMilliseconds(10), NewThreadScheduler.Default)
                          .Select(_ => System.DateTime.Now.ToString("HH:mm:ss.fff")).ToReactiveProperty();
        }
 
        void IDisposable.Dispose()
        {
            this.DateTime.Dispose();
        }
    }
}
タイマーで時間を表示するだけの簡単なサンプルですが、ReactivePropertyをDisposeしないと終了しないアプリケーションになってしまいます。
この場合は、NewThreadSchedulerによって新しいThreadが立っているので当然の結果なのですが、Rxを使うと簡単にThreadを起こせるので、神経質にDisposeしていたほうが良い気がしました。

というわけで、基底クラスとして次のようなものを用意するようにしています。
ViewModelBase.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Text;
using System.Threading.Tasks;

namespace WpfApplication3
{
    public abstract class ViewModelBase : IDisposable
    {
        protected CompositeDisposable Disposable { get; private set; }

        public ViewModelBase()
        {
            this.Disposable = new CompositeDisposable();
        }

        void IDisposable.Dispose()
        {
            this.Disposable.Dispose();
        }
    }
}
CompositeDisposableは、Rxが提供しているIDisposableをまとめるためのクラスです。
これを利用すると、MainViewModelが次のように少し簡易になります。
MainViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using Reactive.Bindings;
 
namespace WpfApplication3
{
    public class MainViewModel : ViewModelBase
    {
        public ReactiveProperty<string> DateTime { get; private set; }
 
        public MainViewModel()
        {
            this.DateTime = 
                Observable.Interval(TimeSpan.FromMilliseconds(10), NewThreadScheduler.Default)
                          .Select(_ => System.DateTime.Now.ToString("HH:mm:ss.fff"))
                          .ToReactiveProperty()
                          .AddTo(this.Disposable); // かずきさん指摘により修正

            // this.Disposable.Add(this.DateTime);
        }
    }
}
ToReactiveProperty()とDisposable.Add()をまとめてうまく書けるといいんですけどね。↓のような、拡張メソッドを増やすのしか思いつきませんでした。
public static class ViewModelBaseEx
{
    public static ReactiveProperty<T> ToReactiveProperty<T>(this IObservable<T> souce, CompositeDisposable disposable)
    {
        var rp = souce.ToReactiveProperty();
        disposable.Add(rp);
        return rp;
    }
}

2015年3月9日

Thicknessの125000倍の長さのGeometryをOnRenderで描画

Filed under: .NET, C#, WPF — タグ: , — yone64 @ 11:15 PM
前回の続きっぽいもの。

CustomControl等でOnRenderをOverrideして描画することが多々あると思いますが(ありますよね!?)
その際は、少し回避方法が異なります。(というか、かなり謎です)
protected override void OnRender(DrawingContext drawingContext)
{
    var geometry = new StreamGeometry();
    using (var context = geometry.Open())
    {
        context.BeginFigure(new Point(0, 100), false, false);
        context.LineTo(new Point(125000, 100), true, false);
    }

    drawingContext.DrawGeometry(null, new Pen(Brushes.Black, 1), geometry);

    base.OnRender(drawingContext);
}
まず、描画できるパターン。125000倍なので、描画可能です。
protected override void OnRender(DrawingContext drawingContext)
{
    var geometry = new StreamGeometry();
    using (var context = geometry.Open())
    {
        context.BeginFigure(new Point(0, 100), false, false);
        context.LineTo(new Point(125000.1, 100), true, false);
    }

    drawingContext.DrawGeometry(null, new Pen(Brushes.Black, 1), geometry);

    base.OnRender(drawingContext);
}
125000倍を超えると描画不可能です。(Lineと同じ)
protected override void OnRender(DrawingContext drawingContext)
{
    var geometry = new StreamGeometry();
    using (var context = geometry.Open())
    {
        context.BeginFigure(new Point(0, 100), false, false);
        context.LineTo(new Point(125000.1, 100.1), true, false);
    }

    drawingContext.DrawGeometry(null, new Pen(Brushes.Black, 1), geometry);

    base.OnRender(drawingContext);
}
ところが、傾けても描画できるようになりません。
protected override void OnRender(DrawingContext drawingContext)
{
    var geometry = new StreamGeometry();
    using (var context = geometry.Open())
    {
        context.BeginFigure(new Point(0, 100), false, false);
        context.LineTo(new Point(0.1, 100), true, false);
    }

    var geometry2 = new StreamGeometry();
    using (var context = geometry2.Open())
    {
        context.BeginFigure(new Point(0, 200), false, false);
        context.LineTo(new Point(375000, 200), true, false);
    }

    drawingContext.DrawGeometry(null, new Pen(Brushes.Transparent, 1), geometry);
    drawingContext.DrawGeometry(null, new Pen(Brushes.Red, 1), geometry2);

    base.OnRender(drawingContext);
}
ちなみに、一つGeometryをDummyで描画しておくと、2つ目のGeometryに対する制限はなくなってるように見えます。(謎謎

Thicknessの125000倍の長さのLine

Filed under: .NET, C#, WPF — タグ: , — yone64 @ 10:47 PM
WPFの制限(?)なのかはわかりませんが、StrokeThicknessの125000倍を超える水平線は引けません。
<Window x:Class="TooLongLine.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <!-- 水平LineはStrokeThicknessの12500倍以下しか描画できない -->

        <!-- 125000倍ちょうどなので描画可能 -->
        <Line X1="0" X2="125000" Y1="5" Y2="5" StrokeThickness="1" Stroke="Red" />
        <!-- 125000倍を超えるので描画不可能 -->
        <Line X1="0" X2="125000.1" Y1="15" Y2="15" StrokeThickness="1" Stroke="Red" />

        <!-- Thicknessを2にすると、125000倍以下になるので描画可能 -->
        <Line X1="0" X2="125000.1" Y1="25" Y2="25" StrokeThickness="2" Stroke="Blue" />
        <!-- 125000倍ちょうどなので描画可能 -->
        <Line X1="0" X2="250000" Y1="35" Y2="35" StrokeThickness="2" Stroke="Blue" />
        <!-- 125000倍を超えるので描画不可能 -->
        <Line X1="0" X2="250000.1" Y1="45" Y2="45" StrokeThickness="1" Stroke="Blue" />

        <!-- 水平でなければ描画可能 -->
        <Line X1="0" X2="250000.1" Y1="55" Y2="55.001" StrokeThickness="1" Stroke="Green" />
        
        <!-- Polylineで、一つの線分が125000倍以下でも水平になってしまうとダメ -->
        <Polyline Points="0,65 100000,65 200000,65" StrokeThickness="1" Stroke="Orange" />
    </Grid>
</Window>
上記、XAMLを実行すると下記Windowが表示されます。

キャプチャ

どうしてもこの制限に引っかかる場合は、微妙に斜めの線にしてみればよいのかもしれません。
その前に、本当にそんなに長いLineが必要かは要検討ですねw

(参考)Horizontal or vertical WPF Lines limited to 125,000 pixels?
http://stackoverflow.com/questions/13731593/horizontal-or-vertical-wpf-lines-limited-to-125-000-pixels

2015年1月26日

Path区切り文字

Filed under: .NET, C# — タグ: — yone64 @ 12:50 PM
.NETにおいて、フォルダパスの区切りは、”\”でも”/”でも問題なく動作します。(たいていの場合
# なお、環境は
# Windows 8.1 + .NET Framework 4.5.1 + Visual Studio 2013 で確認しています。
// 全部動作可能
var readAllLines1 = File.ReadAllLines(@"C:\temp\text.txt");
var readAllLines2 = File.ReadAllLines(@"C:/temp/text.txt");
var readAllLines3 = File.ReadAllLines(@"../../text.txt");
var readAllLines4 = File.ReadAllLines(@"..\..\text.txt");
なぜか、Process.Startを使う場合、”\”じゃないと動作しないケースを発見してしまいました。
// ↓の3つは動作する
Process.Start(@"C:\temp\test.exe");
Process.Start(@"C:/temp/test.exe");
Process.Start(@"..\..\test.exe");
// これだけ、実行時例外
Process.Start(@"../../test.exe");
// これならば実行可能。
Process.Start(@"..\../test.exe");
相対パスで指定する場合の最初の”..\”または”.\”の”\”は”/”にすると動作しないようです。
2番目以降はどちらでも良いようです。意図したものか、バグなのかはわかりませんが、ご注意。
Older Posts »

WordPress.com で無料サイトやブログを作成.