Oui, il y a des moyens. Avec C# 3.0, vous disposez de la Func<T>
qui fait cela.
Par exemple, j'ai écrit ceci hier :
var image = Image.FromFile(_file);
int height = image.Height;
int width = image.Width;
double tan = height*1.00/width;
double angle = (180.0 * Math.Atan(tan) / Math.PI);
var bitmap = new System.Drawing.Bitmap(image, width, height);
var g = System.Drawing.Graphics.FromImage(bitmap);
int fontsize = 26; // starting guess
Font font = null;
System.Drawing.SizeF size;
Func<SizeF,double> angledWidth = new Func<SizeF,double>( (x) =>
{
double z = x.Height * Math.Sin(angle) +
x.Width * Math.Cos(angle);
return z;
});
// enlarge for width
do
{
fontsize+=2;
if (font != null) font.Dispose();
font = new Font("Arial", fontsize, System.Drawing.FontStyle.Bold);
size = g.MeasureString(_text, font);
}
while (angledWidth(size)/0.85 < width);
Le but était d'ajouter un filigrane à une image existante. Je voulais que la taille du texte du filigrane représente environ 85 % de la largeur de l'image. Mais je voulais incliner le texte du filigrane pour qu'il soit écrit sur un angle. Cela a révélé la nécessité d'effectuer quelques calculs trigonométriques basés sur les angles, et je voulais une petite fonction pour effectuer ce travail. Le site Func
est parfait pour cela.
Le code ci-dessus définit un Func
(une fonction) qui accepte un SizeF
et renvoie un double
pour la largeur réelle du texte lorsqu'il est dessiné selon l'angle donné. Ce site Func
est une variable dans une fonction, et la variable elle-même contient une (référence à une) fonction. Je peux alors invoquer cette fonction "privée" dans la portée où je l'ai définie. La fonction a accès aux autres variables qui sont définies avant elle, dans son champ d'exécution. Ainsi, le angle
est accessible dans le cadre de la angledWidth()
fonction.
Si vous voulez une logique invocable qui renvoie void
vous pouvez utiliser Action<T>
de la même manière. .NET définit des génériques Func qui acceptent N arguments, ce qui permet de les rendre assez compliqués. Un Func est comme une fonction VB ou une méthode C# qui renvoie des données non vides ; une Action est comme un Sub VB ou une méthode C# qui renvoie des données vides.
0 votes
Pourquoi voulez-vous faire cela ? Quel problème essayez-vous de résoudre ? Quelle situation essayez-vous de modéliser ?
1 votes
@Cody Gray J'ai une méthode avec beaucoup de code, que je veux structurer pour une meilleure lecture et compréhension. Comme cette partie du code n'est pas nécessaire aux autres méthodes, j'ai pensé à diviser le code à l'intérieur de la méthode.
5 votes
Oui, et c'est exactement pourquoi j'ai demandé. Beaucoup de personnes utiles parlent de lambdas et de
Func
mais ce n'est pas vraiment ce que vous voulez ici. Si vous pensez avoir besoin de refactorer du code à partir d'une méthode existante, créez simplement une nouvelle méthode dans votre fichier.cs
et assurez-vous qu'il est marquéprivate
. Si vous n'avez pas besoin de l'appeler depuis un autre endroit, alors ne le faites pas. Il n'y a aucune raison de compliquer inutilement les choses.0 votes
Duplicata possible de comment créer une fonction à l'intérieur d'une autre fonction en c#, est-ce possible ?
6 votes
Cody Gray : pourquoi chaque structure doit-elle avoir seulement 3 niveaux ? (namespace, class, function) Cela revient à n'avoir que 3 niveaux de profondeur de dossier, ce qui ne sera pas suffisant. C'est l'utilisateur qui décide. Il peut être préférable de placer certaines fonctions de manière à ce qu'elles ne soient pas accessibles à d'autres fonctions de la même classe, car elles peuvent être appelées ensemble ou dans un ordre spécifique. > 20 ans de développement et personne n'a pensé à cela. A la place, nous avons des lambda...
0 votes
@TheTrowser En fait, vous pouvez déjà imbriquer des classes/structures en C#, et bientôt vous pourrez imbriquer des méthodes.