如果问题措辞不佳,我深表歉意,这是一个很难表达或寻找答案的问题,并且将“in”关键字用于逆变代表也无济于事。这是我可以描述它的最佳方式:
设置:
public delegate int TComparer(in T left, in T right);
// an instance of the delegate, initialized elsewhere
private TComparer _comparer;
// an array of T, initialized elsewhere
private T[] data;
'in' 关键字意味着这些操作会引发转换错误:
Array.Sort(data, _comparer); // CS1503
Func<T,T,int> _func = _comparer; // CS1503
因为参数使用'in'关键字的函数与不使用'in'关键字的函数不同,所以在我看来,没有任何方法可以以这种方式将委托(或IComparer等)与关键字一起使用。库中是否有旨在处理这些情况的东西,或者在更具体的情况下是否有另一种方法可以获得相同的效率*?
(* 注意:在这种情况下,T 可能是一个巨大的不可变结构,大量存在并且被频繁访问,因此避免防御性复制非常有用。)
编辑:这是对代码的更完整的了解:
public readonly struct QuadData {
public readonly VertexPositionColorTexture TL; // 6 floats in a struct
public readonly VertexPositionColorTexture TR;
public readonly VertexPositionColorTexture BL;
public readonly VertexPositionColorTexture BR;
public readonly int Depth;
public readonly int TextureCode;
// constructors...
}
public class SpriteBatcher {
public SpriteBatcher() {
_quadBuffer = Array.Empty<QuadData>();
_quadComparer = CompareByDepthDescendingThenTexture;
}
public delegate int QuadDataComparer(in QuadData left, in QuadData right);
private QuadDataComparer _quadDataComparer; // initialized in constructor
private QuadData[] _quadBuffer; // initialized in constructor
public void Update() {
Array.Sort(_quadBuffer, _quadDataComparer); // CS1503
}
}
我认为一些额外的东西不能说明问题本身:
private void OnSetSortingMode(SpriteSortOption sortOption) {
if (sortOption == _sortOption) return;
switch (sortOption) {
case SpriteSortOption.None:
break;
case SpriteSortOption.Texture:
_quadDataComparer = CompareByTexture;
break;
case SpriteSortOption.DepthAscending:
_quadDataComparer = CompareByDepthAscendingThenTexture;
break;
case SpriteSortOption.DepthDescending:
_quadDataComparer = CompareByDepthDescendingThenTexture;
break;
default:
throw new ArgumentException($"Unimplemented SpriteBatcher.SortOptions enumerated value {sortOption} passed to SpriteBatcher.SetSortingMode()");
}
if (sortOption != SpriteSortOption.None) {
_flags |= SpriteBatcherFlags.Sort;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int CompareByTexture(in QuadData x, in QuadData y) {
return y.TextureHashCode - x.TextureHashCode; // int.CompareTo(int) is not needed because we don't actually care if a HashCode is larger or smaller, only different.
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int CompareByDepthAscendingThenTexture(in QuadData x, in QuadData y) {
if (x.Depth < y.Depth) return 1;
if (x.Depth > y.Depth) return -1;
return y.TextureHashCode - x.TextureHashCode; // int.CompareTo(int) is not needed because we don't actually care if a HashCode is larger or smaller, only different.
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int CompareByDepthDescendingThenTexture(in QuadData x, in QuadData y) {
if (x.Depth > y.Depth) return 1;
if (x.Depth < y.Depth) return -1;
return y.TextureHashCode - x.TextureHashCode; // int.CompareTo(int) is not needed because we don't actually care if a HashCode is larger or smaller, only different.
}
public void SetCustomSortOption(QuadDataComparer comparison) {
this._quadDataComparer = comparison;
this._sortOption = SpriteSortOption.Custom;
}