C# 3.5 및 이전 버전에서는 가장 좋은 방법은 단순히 전체 속성 집합을 사용하는 것입니다.
그러나 C# 4.0에서는 찾고자하는 기능을 얻기 위해 dynamic
입력하고 서브 클래스 DynamicObject
을 사용할 수 있습니다. 이것은 더 나은 옵션이 될 수도 있고 그렇지 않을 수도 있습니다.이 기능에 대해 많이 알지 못합니다.
편집 : 나는 그래서 내가 가서이에 C# 4.0 솔루션을 구현하는 것이, 문제에 관심 된
. 코드는 다음과 같습니다. download a full solution if that's more your thing [github]도 가능합니다. 언제나 그렇듯이, 당신이 원하는대로이 코드를 사용/중단/만들 수 있습니다. 하드 드라이브를 지우면 저를 비난하지 마십시오.
편집 3 : 이 내가 여기 만들어 줄게 마지막 편집이지만, 나는 아마이 더 놀거야, 내가 나중에 여기로 오는 사람을위한 최신 링크 된 버전을하겠습니다.
편집 2 :
난 당신이 코드에 들어 가지 전에, 그리고 코드 자체에 Program.Main()
에서 작동하지 않습니다 무슨의 사례가있다.
이제 코드를 참조하십시오.
namespace Swizzle
{
/// <summary>
/// This implements the Vector4 class as described in the question, based on our totally generic
/// Vector class.
/// </summary>
class Vector4 : Vector<int>
{
public Vector4(int val0, int val1, int val2, int val3)
: base(new Dictionary<char, int> { {'t', 0}, {'x', 1}, {'y', 2}, {'z', 3},
{'a', 0}, {'r', 1}, {'g', 2}, {'b', 3}},
new int[] { val0, val1, val2, val3 })
{ }
}
class Program
{
static void Main(string[] args)
{
dynamic v1, v2, v3;
v1 = new Vector4(1, 2, 3, 4);
v2 = v1.rgb;
// Prints: v2.r: 2
Console.WriteLine("v2.r: {0}", v2.r);
// Prints: red: 2
int red = v2.r;
Console.WriteLine("red: {0}", red);
// Prints: v2 has 3 elements.
Console.WriteLine("v2 has {0} elements.", v2.Length);
v3 = new Vector4(5, 6, 7, 8);
v3.ar = v2.gb; // yes, the names are preserved! v3 = (3, 4, 7, 8)
v2.r = 5;
//v2.a = 5; // fails: v2 has no 'a' element, only 'r', 'g', and 'b'
// Something fun that will also work
Console.WriteLine("v3.gr: {0}", v3.gr);
v3.rg = v3.gr; // switch green and red
Console.WriteLine("v3.gr: {0}", v3.gr);
Console.WriteLine("\r\nPress any key to continue.");
Console.ReadKey(true);
}
}
class Vector<T> : DynamicObject
{
private T[] m_values;
private Dictionary<char, int> m_positions;
public Vector(Dictionary<char, int> positions, params T[] values)
{
this.m_positions = positions;
this.m_values = values;
}
public T this[int index] {
get { return this.m_values[index]; }
}
public int Length
{
get { return this.m_values.Length; }
}
public override string ToString()
{
List<string> elements = new List<string>(this.Length);
for (int i = 0; i < this.Length; i++)
{
elements.Add(m_values[i].ToString());
}
return string.Join(", ", elements.ToArray());
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (binder.Name == "Length") {
result = this.Length;
return true;
}
if (binder.Name.Length == 1 && this.m_positions.ContainsKey(binder.Name[0]))
{
result = m_values[this.m_positions[binder.Name[0]]];
return true;
}
Dictionary<char, int> positions = new Dictionary<char, int>(binder.Name.Length);
List<T> values = new List<T>(binder.Name.Length);
int i = 0;
foreach (char c in binder.Name)
{
if (!this.m_positions.ContainsKey(c))
return base.TryGetMember(binder, out result);
values.Add(m_values[m_positions[c]]);
positions.Add(c, i);
i++;
}
result = new Vector<T>(positions, values.ToArray());
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// sanity checking.
foreach (char c in binder.Name)
{
if (!this.m_positions.ContainsKey(c))
return base.TrySetMember(binder, value);
}
Vector<T> vectorValue = value as Vector<T>;
if (vectorValue == null && binder.Name.Length == 1 && value is T)
{
m_values[m_positions[binder.Name[0]]] = (T)value;
return true;
}
else if (vectorValue == null)
throw new ArgumentException("You may only set properties of a Vector to another Vector of the same type.");
if (vectorValue.Length != binder.Name.Length)
throw new ArgumentOutOfRangeException("The length of the Vector given does not match the length of the Vector to assign it to.");
int i = 0;
foreach (char c in binder.Name)
{
m_values[m_positions[c]] = vectorValue[i];
i++;
}
return true;
}
}
}
내 대답에 편집을 참조하십시오, 나는이 문제에 대한 실제 작업 솔루션을 포함 시켰습니다,하지만 당신은 항상 그것을 더 일반화하고 그것을'벡터'만들 수있는 C# 4.0 –