Skip to content

Instantly share code, notes, and snippets.

@ufcpp
Created August 11, 2017 14:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ufcpp/e9c2a8f3389c04353ffcd1404831e410 to your computer and use it in GitHub Desktop.
Save ufcpp/e9c2a8f3389c04353ffcd1404831e410 to your computer and use it in GitHub Desktop.
string と char[] の FieldOffset を重ねてしまう
using System;
using System.Runtime.InteropServices;
//
[StructLayout(LayoutKind.Explicit)]
struct StringOrCharArray
{
[FieldOffset(0)]
private StringSegment _string;
// ArraySegment の private field の並びが 配列, int, int になっているという前提。
// 一応 Mono と CoreCLR ではこの並びになってるけども、割かし危険な類の前提なのでやるかどうか悩むところ
[FieldOffset(0)]
private ArraySegment<char> _array;
// is string 判定用に、StringSegment._string と ArraySegment<T>._array の位置に重ねて object 型のフィールドを定義
[FieldOffset(0)]
private object _obj;
public StringOrCharArray(string s) : this() => _string = new StringSegment(s, 0, s.Length);
public StringOrCharArray(string s, int offset, int count) : this() => _string = new StringSegment(s, offset, count);
public StringOrCharArray(char[] s) : this() => _array = new ArraySegment<char>(s, 0, s.Length);
public StringOrCharArray(char[] s, int offset, int count) : this() => _array = new ArraySegment<char>(s, offset, count);
private bool IsString => _obj is string;
// 動作確認用なので、とりあえず ToString だけ実装
public override string ToString() => IsString ? _string.ToString() : new string(_array.Array, _array.Offset, _array.Count);
}
struct StringSegment
{
string _string;
int _offset;
int _count;
public StringSegment(string s, int offeset, int count)
{
_string = s;
_offset = offeset;
_count = count;
}
public override string ToString() => _string.Substring(_offset, _count);
}
class Program
{
static void Main()
{
Console.WriteLine(new StringOrCharArray("abcdefg"));
Console.WriteLine(new StringOrCharArray("abcdefg", 2, 3));
Console.WriteLine(new StringOrCharArray(new[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g' }));
Console.WriteLine(new StringOrCharArray(new[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g' }, 2, 3));
// string, int, int もしくは char[], int, int を完全に重ねてあるので、構造体サイズが16
Console.WriteLine(System.Runtime.CompilerServices.Unsafe.SizeOf<StringOrCharArray>());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment