Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

163
Visualizações
Cambiar la firma del delegado en la biblioteca para omitir un argumento no interrumpe las aplicaciones que lo usan

Considere el siguiente código en una biblioteca de clases:

 public class Service { public delegate string Formatter(string s1, string s2); public void Print(Formatter f) { Console.WriteLine(f("a", "b")); } }

Y aquí hay una aplicación de consola que lo usa:

 static void Main(string[] args) { s = new Service(); s.Print(Concat); } static string Concat(string s1, string s2) { return string.Format("{0}-{1}", s1, s2); }

Hasta ahora imprime " ab ", tal como cabría esperar.

Ahora, cambio la biblioteca de clases de la siguiente manera:

 public class Service { public delegate string Formatter(string s1); public void Print(Formatter f) { Console.WriteLine(f("a")); } }

Es decir, eliminé un parámetro del delegado. Compilo solo la biblioteca de clases y sobrescribo el dll que se encuentra junto a la aplicación de la consola (la aplicación de la consola no se vuelve a compilar). Espero que este sea un cambio importante en la biblioteca y si ejecuto la aplicación, encuentra la falta de coincidencia, lo que resulta en alguna excepción de tiempo de ejecución.

Por el contrario, cuando ejecuto la aplicación no hay ninguna excepción y obtengo el sorprendente resultado " -a ". Cuando depuro, puedo ver que se llama al método Concat (con 2 parámetros), el nivel de la pila de llamadas a continuación muestra la llamada de impresión a f ("a") (un parámetro), sin indicación de error en ninguna parte. Lo más interesante es que en Concat s1 es nulo, s2 es "a".

También jugué con diferentes cambios en la firma (agregando parámetros, cambiando el tipo de parámetro) en su mayoría con el mismo resultado. Cuando cambié el tipo de s2 de string a int, obtuve una excepción, pero no cuando se llamó al método Concat, sino cuando intentó llamar a string.Format.

Lo probé con .NET target framework 4.5.1 y 3.5, x86 y x64.

¿Alguien puede responder si este es el comportamiento esperado o un error? Me parece bastante peligroso.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Aquí hay una reproducción más simple: básicamente, estoy usando el constructor "bajo el capó" en el tipo de delegado (el que usa IL) para pasar un objetivo de método con la firma incorrecta, y ... funciona bien (por lo cual Quiero decir que no arroja una excepción, se comporta como su código):

 using System; static class P { static void Main() { // resolve the (object, IntPtr) ctor var ctor = typeof(Func<string, string>).GetConstructors()[0]; // resolve the target method var mHandle = typeof(P).GetMethod(nameof(Concat)) .MethodHandle.GetFunctionPointer(); object target = null; // because: static // create delegate instance var del = (Func<string, string>)ctor.Invoke(new object[] { target, mHandle }); var result = del("abc"); Console.WriteLine(result); // "-abc" } public static string Concat(string s1, string s2) { return string.Format("{0}-{1}", s1, s2); } }

Esto no es realmente una explicación. ¡Pero podría ser útil si desea preguntarle a alguien más experto en CLR! Hubiera esperado que el constructor delegado se quejara en voz alta de que el objetivo era incorrecto.

Como suposición (pura especulación), es un caso de: si está pasando un IntPtr (int nativo), entonces está completamente solo: el código hace lo más rápido posible. ¡Sin embargo, parece una trampa desagradable para los incautos!

En cuanto a por qué s2 tiene el valor y s1 está vacío: supongo que se debe a que la pila se acumula hacia abajo (no hacia arriba), por lo tanto, en un método de dos parámetros, arg1 es el parámetro inmediatamente adyacente a la posición anterior en la pila. Cuando pasamos un solo valor en lugar de dos, solo ponemos un valor debajo, por lo que s2 tiene un valor y s1 no está definido (podría ser basura del código anterior).

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda