Для простоты вы можете встроить их в горизонтальное UIStackview
и установить
self.rightlb.isHidden = true
, и оно автоматически исчезнет без ширины, также в вашем текущем коде убедитесь, что
tableCell?.layoutIfNeeded()
после изменения ограничений
Ох, это совсем не просто. Func
представляет общий делегат
, а не выражение. Если есть какой-либо способ сделать это (из-за оптимизаций и других действий, выполняемых компилятором, некоторые данные могут быть выброшены, поэтому может оказаться невозможным вернуть исходное выражение), это будет разборка IL на лету и вывод выражения (что ни в коем случае не легко). Обработка лямбда-выражений как данных ( Expression
) - это магия, совершаемая компилятором (в основном компилятор создает дерево выражений в коде вместо компиляции в IL)
Вот почему языки, которые толкают лямбды до крайности (например, Лисп), часто проще реализовать как интерпретаторы . В этих языках код и данные по сути одно и то же (даже во время выполнения ), но наш чип не может понять эту форму кода, поэтому мы должны эмулировать такую машину, создавая интерпретатор поверх тот, кто понимает это (выбор, сделанный Lisp-подобными языками) или жертвуя силой (код больше не будет точно соответствовать данным) в некоторой степени (выбор, сделанный C #). В C # компилятор создает иллюзию обработки кода как данных, позволяя интерпретировать лямбда-символы как код ( Func
) и данные ( ] Выражение
) во время компиляции .
Func
) и данные ( ] Выражение >
) во время компиляции . таким образом, мы должны эмулировать такую машину, создавая поверх нее интерпретатор, который понимает ее (выбор, сделанный Lisp-подобными языками) или жертвуя силой (код больше не будет точно равен данным) в некоторой степени (выбор сделан по C #). В C # компилятор создает иллюзию обработки кода как данных, позволяя интерпретировать лямбда-символы как код ( Func
) и данные ( ] Выражение >
) во время компиляции . Вы можете пойти другим путем через метод .Compile (), однако - не уверен, что это полезно для вас:
public void ContainTheDanger<T>(Expression<Func<T>> dangerousCall)
{
try
{
var expr = dangerousCall.Compile();
expr.Invoke();
}
catch (Exception e)
{
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger = ((MethodCallExpression)dangerousCall.Body).Method.Name;
throw new DangerContainer("Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
var thing = new Thing();
ContainTheDanger(() => thing.CrossTheStreams());
}
Что вы, вероятно, должны сделать, это перевернуть метод. Возьмите Expression>, и скомпилируйте и запустите. Если это не помогло, у вас уже есть выражение, на которое вы можете посмотреть.
public void ContainTheDanger(Expression<Func<T>> dangerousCall)
{
try
{
dangerousCall().Compile().Invoke();;
}
catch (Exception e)
{
// This next line does not work...
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
Очевидно, что вам нужно учесть последствия этого для производительности и определить, действительно ли это то, что вам действительно нужно сделать.
Если вам иногда нужно выражение, а иногда делегат, у вас есть 2 варианта:
Expression <...>
и просто .Compile (). Invoke (...)
, если вы хотите делегата. Очевидно, что это дорого. JB Evain из команды Cecil Mono делает некоторые успехи, чтобы включить это
http://evain.net/blog/articles/2009/04/22/converting-delegates-to -expression-trees