Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
262 views
in Technique[技术] by (71.8m points)

c# - Is there a way to access T.Method() in a new instance of T in a generic method?

I have a generic method

class Program {
    Character CreateChar<T>() where T : new() {
        T DChar = new T();
        Character Char = new Character {
            Name = DChar.Name,
            Health = DChar.Health
        };
        return Char;
    }
    public static void Main() {
        Character Char1 = CreateChar<Mage>();
    }
}

Where I have a Character class, and that has the basic stuff like Name, Health, ect.

class Character {
    public string Name { get; set; }
    public int Health { get; set; }
}

But (this is like a game) I have some set types like "Mage".

class Mage {
    public int Health {
        get {
            return 5;
        }
    }
}

So my idea was to make a generic method "CreateChar" so I can pass Mage to it like so in Main:

 Character Char1 = CreateChar<Mage>();

However I can't seem to access DChar.Name or DChar.Health since "T does not contain a definition for 'Health'". So, is there a way to access the T method? Or is there just a better way of handling this?

In fact, now that I see it, "CreateChar();" is invalid as well because "an object reference is required for a nonstatic field". So I guess my question is, what is wrong, and how do I fix it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In a generic method, you can only access the methods defined by the constraint on T (unless you use reflection or type checking/casting, both of which defeat the purpose of generics). If you constrain T to a Character (which I think you have to do to access Name and Health), then it should work (please post the Character class with relevant properties). But then in order to pass it a Mage, you'd have to have Mage inherit from Character.

Here's what I mean; first create an interface that defines properties that all characters will have (i.e. all public properties, methods, and events):

public interface ICharacter
{
    string Name { get; set; }
    string Description { get; }
    int Health { get; set; }
}

Then we can create a base class called Character that implements the interface::

public class Character :  ICharacter
{
    public string Name { get; set; } = "Default Character";
    public int Health { get; set; } = 5;
    public string Description { get; protected set; } = "Default Description";
}

Next we create some character types that inherit the Character class:

public class Mage : Character
{
    public Mage()
    {
        Name = "Default Mage";
        Description = "Someone who uses or practices magic " + 
            "derived from supernatural or occult sources.";
    }
}

public class Elf : Character
{
    public Elf()
    {
        Name = "Default Elf";
        Description = "A supernatural creature of folk tales, " + 
            "typically represented as a small, elusive figure " + 
            "in human form with pointed ears, magical powers, " + 
            "and a capricious nature.";
    }
}

So now we can constrian our generic type T to the ICharacter interface, and we can access the Name and Health properties:

class Program
{
    T CreateChar<T>() where T : ICharacter, new()
    {
        var result = new T();
        result.Name += " (created in 'CreateChar' method)";  // Modify a property
        return result;
    }

    // Rest of class omitted
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...