Skip to content

Instantly share code, notes, and snippets.

@hsytkm
Created May 23, 2023 21:33
Show Gist options
  • Save hsytkm/3d74415a9267d2fb0a9834b4d6a9fc9f to your computer and use it in GitHub Desktop.
Save hsytkm/3d74415a9267d2fb0a9834b4d6a9fc9f to your computer and use it in GitHub Desktop.
C# Owner Belongings
namespace ConsoleApp1;
public interface IBelonging<T>
where T : IBelonging<T>
{
static abstract Owner<T> Create();
}
public readonly record struct Owner<T> : IDisposable
where T : IBelonging<T>
{
private readonly T _value;
private readonly Action<T>? _release;
public bool IsNone => _release is null;
public T Value
{
get
{
if (IsNone) throw new InvalidOperationException();
return _value;
}
}
public Owner(T value, Action<T> release)
{
_value = value ?? throw new ArgumentNullException(nameof(value));
_release = release ?? throw new ArgumentNullException(nameof(release));
}
public void Dispose() => _release?.Invoke(_value);
}
public sealed class MyObject : IBelonging<MyObject>
{
private MyObject() { }
~MyObject() => _release(this);
private static readonly Action<MyObject> _release = static self =>
{
Console.WriteLine("Disposed MyObject");
};
public static Owner<MyObject> Create() => new(new MyObject(), _release);
}
// [(C#) オブジェクトの破棄の可否を型で制限する - ネコのために鐘は鳴る](https://ikorin2.hatenablog.jp/entry/2023/02/13/072121)
using ConsoleApp1;
Owner<MyObject> obj = MyObject.Create();
UseObject1(obj.Value);
UseObject2(obj);
void UseObject1(MyObject obj)
{
// MyObject を使う。
// 破棄出来ない (== 破棄しなくてよい)
}
void UseObject2(Owner<MyObject> obj)
{
// MyObject を使う。
// ここで破棄する (== 破棄する責任があることが型で明示されている)
obj.Dispose();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment