Resources on Covariance and Contravariance

Eric Lippert is on the C# Compiler team and has written a series of posts on this topic that are an absolute must-read!

  1. Part One
  2. Part Two: Array Covariance (and Why is covariance of value-typed arrays inconsistent?)
  3. Part Three: Method Group Conversion Variance
  4. Part Four: Real Delegate Variance
  5. Part Five: Higher Order Functions Hurt My Brain
  6. Part Six: Interface Variance
  7. Part Seven: Why Do We Need A Syntax
  8. Part Eight: Syntax Options
  9. Part Nine: Breaking Changes
  10. Part Ten: Dealing With Ambiguity
  11. Part Eleven: To infinity, but not beyond

MSDN

The information here is quite “flat”, but still worth a read.

More

Category Theory

The names covariance and contravariance in C# derive from co- and contravariant functors described in category theory.

Hope that helps!

Advertisement

.NET 4.0 types with added support for co- or contravariance

Just a plain list of types from the .NET 4.0 Base Class Library where Microsoft has added support for covariance (out) and contravariance (in).

in System

// Delegates
Action<in T1[..in T16]>
Func<out TResult>
Func<in T1[..in T16], out TResult>
Comparison<in T>
Converter<in TInput, out TOutput>
Predicate<in T> 

// Interfaces
IComparable<in T>
IObservable<out T>
IObserver<in T>

in System.Collections.Generic

IComparer<in T> 
IEnumerable<out T> 
IEnumerator<out T> 
IEqualityComparer<in T> 

in System.Linq

IGrouping<out TKey,out TElement> 
IOrderedQueryable<out T> 
IQueryable<out T>

Size calculations for image resizing (C#)

I just reused some code I wrote a couple of years ago, and thought I’d share it here.

It’s not about the best ways to resize images. If that is what you search for, have a look at this 🙂

It’s rather some code for calculating the size of the target image from the originals size while applying one of four rules:

  • Fit: Often you want to fit the image into a box – but without stretching it. So if you have a image that is 50×100 and you want to fit it into 50×50, the result is 25×100. If the original is 100×50, the result would be 50×25. Getting it?
  • Stretch: Not to useful, but sometimes needed 🙂
  • FixedHeight: Maintain the ratio, adjust to height.
  • FixedWidth: Maintain the ration, adjust to width.

Usage

Pretty straight-forward, I think.

var _100_50 = new Size(100, 50);
ResizeType.Fit.CalcNewSize(_100_50, new Size(50, 50), true)
    .Satisfy(s => s.Width == 50 && s.Height == 25);

var _50_100 = new Size(50, 100);

ResizeType.Fit.CalcNewSize(_50_100, new Size(50, 50), true)
    .Satisfy(s => s.Width == 25 && s.Height == 50);

ResizeType.Stretched.CalcNewSize(_50_100, new Size(500, 500), false)
    .Satisfy(s => s.Width == 50 && s.Height == 100);

ResizeType.FixedHeight.CalcNewSize(_50_100, new Size(0, 50), false)
    .Satisfy(s => s.Width == 25 && s.Height == 50);

* The Satisfy-Method is from SharpTestEx.

Code

Have fun! 🙂

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

namespace lcorneliussen
{
    public interface IResizeType
    {
        Size CalcNewSize(Size currentSize, Size newSize, bool resizeIfSmaller);
    }

    /// <summary>
    /// Offers some helpful methods for image resizing.
    /// </summary>
    public class ResizeType
    {
        /// <summary>
        /// Returns the new size by fixed height.
        /// </summary>
        public static IResizeType FixedHeight = new FixedHeightResizeType();

        /// <summary>
        /// Returns the new size by fixed width.
        /// </summary>
        public static IResizeType FixedWidth = new FixedWidthResizeType();

        /// <summary>
        /// Returns a size wich fits in a target size.
        /// </summary>
        public static IResizeType Fit = new FitResizeType();

        /// <summary>
        /// Stretches a image to the given size.
        /// </summary>
        public static IResizeType Stretched = new StretchedResizeType();

        private static int CalcNewHeight(int currentWidth, int currentHeight, int newWidth)
        {
            float ratio = (float)newWidth / (float)currentWidth;
            float newHeight = currentHeight * ratio;

            return (int)newHeight;
        }

        private static int CalcNewWidth(int currentWidth, int currentHeight, int newHeight)
        {
            float ratio = (float)newHeight / (float)currentHeight;
            float newWidth = currentWidth * ratio;

            return (int)newWidth;
        }

        private class FixedHeightResizeType : IResizeType
        {
            public Size CalcNewSize(Size currentSize, Size newSize, bool resizeIfSmaller)
            {
                int height = newSize.Height;

                if (!resizeIfSmaller)
                {
                    if (height > currentSize.Height) height = currentSize.Height;
                }

                int newWidth = CalcNewWidth(currentSize.Width, currentSize.Height, height);
                return new Size(newWidth, height);
            }
        }

        private class FixedWidthResizeType : IResizeType
        {
            public Size CalcNewSize(Size currentSize, Size newSize, bool resizeIfSmaller)
            {
                int width = newSize.Width;
                
                if (!resizeIfSmaller)
                {
                    if (width > currentSize.Width) width = currentSize.Width;
                }

                int newHeight = CalcNewHeight(currentSize.Width, currentSize.Height, width);
                return new Size(width, newHeight);
            }
        }

        private class FitResizeType : IResizeType
        {
            public Size CalcNewSize(Size currentSize, Size newSize, bool resizeIfSmaller)
            {
                int width = newSize.Width;
                int height = newSize.Height;

                int newWidth = currentSize.Width;
                int newHeight = currentSize.Height;

                if (!resizeIfSmaller) // break, if newSize allready fits in currentSize
                    if (currentSize.Height < height && currentSize.Width < width)
                        return new Size(currentSize.Width, currentSize.Height);

                if(width != newWidth) // shrink or expand to width
                {
                    newHeight = CalcNewHeight(currentSize.Width, currentSize.Height, width);
                    newWidth = width;
                }
                if (newHeight > height) //shrink to fit height, if neccesarry
                {
                    newWidth = CalcNewWidth(newWidth, newHeight, height);
                    newHeight = height;
                }

                return new Size(newWidth, newHeight);
            }
        }

        private class StretchedResizeType : IResizeType
        {
            public Size CalcNewSize(Size currentSize, Size newSize, bool resizeIfSmaller)
            {
                int w = newSize.Width;
                int h = newSize.Height;

                if (!resizeIfSmaller)
                {
                    if (w > currentSize.Width) w = currentSize.Width;
                    if (h > currentSize.Height) h = currentSize.Height;
                }

                return new Size(w, h);
            }
        }
    }
}

* this code on gist

RT: History of Programming Languages

.

.

1996 – James Gosling invents Java. Java is a relatively verbose, garbage collected, class based, statically typed, single dispatch, object oriented language with single implementation inheritance and multiple interface inheritance. Sun loudly heralds Java’s novelty.

2001 – Anders Hejlsberg invents C#. C# is a relatively verbose, garbage collected, class based, statically typed, single dispatch, object oriented language with single implementation inheritance and multiple interface inheritance. Microsoft loudly heralds C#’s novelty.

.

.

From: One Div Zero: A Brief, Incomplete, and Mostly Wrong History of Programming Languages